具有corePoolSize 0的ThreadPoolExecutor在任务队列已满之前不应执行任务

Ste*_*eve 6 java concurrency multithreading threadpool java-threads

我正在经历Java Concurrency In Practice并且陷入8.3.1线程创建和拆解主题.以下脚注警告要保持corePoolSize零.

开发人员有时会试图将核心大小设置为零,这样工作线程最终会被拆除,因此不会阻止JVM退出,但这可能会导致在不使用a的线程池中出现一些看似奇怪的行为.用于工作队列的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"));
    }
Run Code Online (Sandbox Code Playgroud)

输出: 你好

那么,程序的行为是否表明ThreadPoolExecutor如果提交任务而无论如何都会创建至少一个线程corePoolSize=0.如果是,那么教科书中的警告是什么.

编辑:在@ SK的建议下测试了jdk1.5.0_22中的代码,并进行了以下更改:

ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(1));//Queue size is set to 1.
Run Code Online (Sandbox Code Playgroud)

但是通过此更改,程序终止而不打印任何输出.

我是否误解了书中的这些陈述?

编辑(@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.");
}
Run Code Online (Sandbox Code Playgroud)

@sjlee已将结果发布在评论中.

Ste*_*n C 6

ThreadPoolExecutor当核心池大小为零时,Java 5 中的这种奇怪行为显然被认为是一个错误,并在 Java 6 中悄然修复。

事实上,由于 Java 6 和 7 之间的一些代码返工,该问题在 Java 7 中再次出现。然后将其报告为错误,确认为错误并修复。

无论哪种方式,您都不应该使用受此错误影响的 Java 版本。Java 5 已于 2015 年终止生命,Java 6 及更高版本的最新可用版本不受影响。“Java 并发实践”的那一部分不再合适了。

参考: