Java线程池为什么核心线程数为0依然能执行?

Java线程池为什么核心线程数为0依然能执行?,第1张

Java线程池为什么核心线程数为0依然能执行?

下面这段代码的线程会执行吗?

ExecutorService es = 
new ThreadPoolExecutor(0, 100000, 100000, TimeUnit.HOURS,new linkedBlockingQueue<>());

答案是会。
但是为啥?

通过线程池的 execute 方法可以看到:

接着思考:
有没有进入队列
先进入队列还是先创建线程?
都调用了队列的什么方法?

看最终代码:

public static void main(String[] args) {

         class MyQueue implements InvocationHandler {
             private BlockingQueue queue = null;
             public MyQueue(BlockingQueue queue){
                 this.queue = queue;
             }
             @Override
             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                 System.out.println(method.getName() + "::::::::::::::::::::::::::" + Arrays.toString(args));
                 return method.invoke(queue,args);
             }
         }

        linkedBlockingQueue queue = new linkedBlockingQueue();
        BlockingQueue queue2 = (BlockingQueue)Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{BlockingQueue.class},new MyQueue(queue));

        ExecutorService es = new ThreadPoolExecutor(1, 1, 100000, TimeUnit.HOURS, queue2, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                System.out.println("--------------------- new Thread ------------------------");
                return new Thread(r);
            }
        });
        es.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello : " + Thread.currentThread().getId());
                try {
                    Thread.sleep( 1 * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public String toString() {
                return "------------ test obj -------------";
            }
        });

        es.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello : " + Thread.currentThread().getId());
                try {
                    Thread.sleep( 1 * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public String toString() {
                return "------------ test obj -------------";
            }
        });
    }

变换ThreadPoolExecutor对象的第一个参数核心线程数:
核心线程数是0:
先走队列后走线程,执行的是队列的offer与poll

核心线程数大于0:
注意实际线程要大于核心线程数!
先走线程在走offer与take

核心线程数大于0:
注意实际线程要小于等于核心线程数!
先走线程,并且只走take

如果切换队列对象呢?

public static void main(String[] args) {

         class MyQueue implements InvocationHandler {
             private BlockingQueue queue = null;
             public MyQueue(BlockingQueue queue){
                 this.queue = queue;
             }
             @Override
             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                 System.out.println(method.getName() + "::::::::::::::::::::::::::" + Arrays.toString(args) + "t" + Thread.currentThread().getId());
                 return method.invoke(queue,args);
             }
         }

        BlockingQueue queue = new SynchronousQueue();
        BlockingQueue queue2 = (BlockingQueue)Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{BlockingQueue.class},new MyQueue(queue));

        ExecutorService es = new ThreadPoolExecutor(1, 5, 2, TimeUnit.HOURS, queue2, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                System.out.println("--------------------- new Thread ------------------------");
                return new Thread(r);
            }
        });
        es.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello : " + Thread.currentThread().getId());
                try {
                    Thread.sleep( 1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public String toString() {
                return "------------ test obj -------------";
            }
        });

        es.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello : " + Thread.currentThread().getId());
                try {
                    Thread.sleep( 1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public String toString() {
                return "------------ test obj -------------";
            }
        });
        es.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello : " + Thread.currentThread().getId());
                try {
                    Thread.sleep( 1 * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public String toString() {
                return "------------ test obj -------------";
            }
        });
    }

再次尝试,注意观察线程ID

最终的出来的结论是:
1、当核心线程数为0的时候,会创建一个非核心线程进行执行
2、核心线程数不为0的时候,如果核心线程数在执行,会有一个非核心线程数从队列中取对象执行线程
3、核心线程数执行的是队列的take,非核心线程数执行队列的offer和poll
4、核心线程数不为0且队列为SynchronousQueue时,就成了单线程运行了

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5693636.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存