使用ThreadPoolExecutor,allowCoreThreadTimeOut和零核心线程之间有什么区别?

时间:2019-04-27 09:30:55

标签: java multithreading threadpoolexecutor

阅读ThreadPoolExecutor的文档后,我很困惑以下内容与示例用法之间的区别:

零核心线程和十个最大线程,后者在2秒后超时:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, // core threads
        10, // max threads
        2000, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>(),
        Executors.defaultThreadFactory()
);

十个核心线程和十个最大线程在2秒后都超时:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
        10, // core threads
        10, // max threads
        2000, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>(),
        Executors.defaultThreadFactory()
);

executor.allowCoreThreadTimeOut(true);

这些执行者的行为是否有所不同?

1 个答案:

答案 0 :(得分:2)

您可以阅读动机here

  

我想要固定线程池之类的东西   (Executors.newFixedThreadPool()),但是线程在它们死时会死掉   闲置时间过长,并在再次需要它们时重新创建。

     

最直观的方法-将核心大小设置为0,最大池大小设置为   边界值,以及队列到[无界队列]   -失败:根本没有执行任何任务(与Javadoc一致,但是-恕我直言-有点违反直觉)。

executor.allowCoreThreadTimeOut(true);可用于获得此行为。

更多详细信息,如果指定了corePoolSize = 0,为什么根本不执行任何任务

在Javadoc中,

  

使用无限制队列(例如,不带队列的LinkedBlockingQueue   预定义的容量)将导致新任务在以下情况下在队列中等待   所有corePoolSize线程都很忙。因此,不超过corePoolSize   线程将永远被创建。 (以及maximumPoolSize的值   因此没有任何作用。)

因此,如果您指定corePoolSize = 0,将不会创建任何线程,也不会执行任何任务。

实际上,,当corePoolSize为零时,实现会创建一个线程(已通过Sun JDK6和OpenJDK11测试)。因此在实践中,将执行任务 ,但是无论指定什么maximumPoolSize,都不会创建一个以上的线程。我不完全确定为什么,因为根据规范,它甚至不应创建一个。

下面是我的测试代码。这只会使用一个线程,但是如果指定corePoolSize=10,它将使用10。如果添加allowCoreThreadTimeOut(true),则这些线程可能会超时。

LinkedBlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, // core threads
        10, // max threads
        2, TimeUnit.MILLISECONDS,
        q
);

for (int i = 0; i < 10; i++) {
    final int j = i;
    executor.execute(() ->
        {
           try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           System.out.println(
               "TaskNo:" + j + ":" + Thread.currentThread().getName()
           );
         });
}

executor.shutdown();