具有 corePoolSize 0 的 ThreadPoolExecutor 不应在任务队列已满之前执行任务 [英] ThreadPoolExecutor with corePoolSize 0 should not execute tasks until task queue is full

查看:38
本文介绍了具有 corePoolSize 0 的 ThreadPoolExecutor 不应在任务队列已满之前执行任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Java 并发实践,但在8.3.1 线程创建和拆卸主题上遇到了困难.以下脚注警告将 corePoolSize 保持为零.

I was going through Java Concurrency In Practice and got stuck at the 8.3.1 Thread creation and teardown topic. The following footnote warns about keeping corePoolSize to zero.

开发人员有时会试图将核心大小设置为零,以便工作线程最终被拆除,因此不会阻止 JVM 退出,但这可能会导致一些不使用 SynchronousQueue 作为其工作队列的线程池中的奇怪行为(就像 newCachedThreadPool 一样).如果池已经是核心大小,ThreadPoolExecutor 创建仅当工作队列已满时才创建新线程.所以任务提交到一个带有工作队列的线程池具有任何容量且核心大小为零的程序在队列填满之前不会执行,这通常是不是想要的.

Developers are sometimes tempted to set the core size to zero so that the worker threads will eventually be torn down and therefore won’t prevent the JVM from exiting, but this can cause some strange-seeming behavior in thread pools that don’t use a SynchronousQueue for their work queue (as newCachedThreadPool does). If the pool is already at the core size, ThreadPoolExecutor creates a new thread only if the work queue is full. 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, which is usually not what is desired.

所以为了验证这一点,我编写了这个程序,但它不像上述那样工作.

So to verify this I wrote this program which does not work as stated above.

    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"));
    }

输出:你好

那么,程序的行为是否表明 ThreadPoolExecutor 在提交任务时至少创建一个线程,而与 corePoolSize=0 无关.如果是,那么教科书上的警告是什么.

So, does the behavior of the program suggest that ThreadPoolExecutor creates at least one thread if a task is submitted irrespective of corePoolSize=0. If yes, then what is the warning about in the text book.

根据@S.K. 的建议测试了 jdk1.5.0_22 中的代码,并进行了以下更改:

Tested the code in jdk1.5.0_22 upon @S.K.'s suggestion with following change:

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

但是随着这个变化,程序终止而不打印任何输出.

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

EDIT (@sjlee): 很难在评论中添加代码,所以我将其添加为此处的编辑...最新的 JDK 和 JDK 1.5?

EDIT (@sjlee): It's hard to add code in the comment, so I'll add it as an edit here... Can you try out this modification and run it against both the latest JDK and 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 在评论中发布了结果.

@sjlee Have posted the result in comments.

推荐答案

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

This odd behavior of ThreadPoolExecutor in Java 5 when the core pool size is zero was apparently recognized as a bug and quietly fixed in Java 6.

确实,由于在 6 和 7 之间重新修改了一些代码,该问题在 Java 7 中再次出现.然后它被报告为错误,确认为错误并已修复.

Indeed, the problem reappeared in Java 7 as a result of some code reworking between 6 and 7. It was then reported as a bug, acknowledged as a bug and fixed.

无论哪种方式,您都不应该使用受此错误影响的 Java 版本.Java 5 已于 2015 年停产,Java 6 及更高版本的最新可用版本不受影响.Java 并发实践"的那部分不再合适.

Either way, you should not be using a version of Java that is affected by this bug. Java 5 was end-of-life in 2015, and the latest available versions of Java 6 and later are not affected. That section of "Java Concurrency In Practice" is no longer apropos.

参考文献:

  • http://cs.oswego.edu/pipermail/concurrency-interest/2006-December/003453.html (read the entire thread)
  • http://gee.cs.oswego.edu/dl/concurrency-interest/index.html (see the version of ThreadPoolExecutor in the JSR166y bundle.)
  • https://bugs.openjdk.java.net/browse/JDK-7091003)

这篇关于具有 corePoolSize 0 的 ThreadPoolExecutor 不应在任务队列已满之前执行任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆