阅读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);
这些执行者的行为是否有所不同?
答案 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();