我正在经历Java 并发实践并被困在8.3.1 线程的创建和销毁话题。以下脚注警告不要保留corePoolSize
为零。
开发人员有时会试图将核心大小设置为零,以便工作线程
最终会被拆除,因此不会阻止 JVM 退出,但这可能会导致一些问题
不使用 SynchronousQueue 作为工作队列的线程池中看似奇怪的行为
(就像 newCachedThreadPool 所做的那样)。如果池已经达到核心大小,ThreadPoolExecutor 会创建
仅当工作队列已满时才创建新线程。所以任务提交到带有工作队列的线程池
具有任何容量且核心大小为零的任务在队列填满之前不会执行,通常是
不是想要的。
因此,为了验证这一点,我编写了这个程序,该程序无法按上述方式工作。
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
Output:
Hello
那么,程序的行为是否表明ThreadPoolExecutor
如果提交任务,则创建至少一个线程,无论corePoolSize=0
。如果是的话,那么教科书上的警告是什么?
EDIT:测试了代码jdk1.5.0_22根据 @S.K. 的建议进行以下更改:
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1));//Queue size is set to 1.
但通过此更改,程序将终止而不打印任何输出。
那么我是否误解了书中的这些陈述?
编辑(@sjlee):在注释中添加代码很困难,所以我将其添加为此处的编辑...您可以尝试此修改并针对最新的 JDK 和 JDK 1.5 运行它吗?
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
tp.shutdown();
if (tp.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("thread pool shut down. exiting.");
} else {
System.out.println("shutdown timed out. exiting.");
}
@sjlee 已在评论中发布了结果。