并发 - 如何让它排队而不拒绝?

concurrency - How to make it queue and not reject?

这里使用用户 sjlee 给出的答案 Impossible to make a cached thread pool with a size limit?

附码

new ThreadPoolExecutor(100, // core size
    10000, // max size
    1000, // idle timeout
    TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>(Integer.MAX_SIZE)); // queue with a size

如果有超过 coreSize 100 * queueSize 20 个任务,线程数将增加直到达到最大大小。

好的。

但问题是,假设一切都完成了,没有更多的任务,线程数不会减少。

如何让Executor在空闲时将线程数减为0?

接下来,如何让 Executor 将 extras 排队到 运行 之后?

您可以使用allowCoreThreadTimeOut(true)来做到这一点,核心线程会在超时时终止。

Using the answer given by user sjlee here Impossible to make a cached thread pool with a size limit?

我不确定您是否完全理解链接到的答案。它指出,启动超过核心线程的唯一方法是队列已满。因此,如果我们查看您的代码:

new ThreadPoolExecutor(100, // core size
    10000, // max size
    1000, // idle timeout
    TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>(Integer.MAX_SIZE)); // queue with a size

这意味着您永远不会启动第 101 个线程,除非您确实将 2^31-1 个任务排入线程池。我不认为你真的应该启动 10,000 个线程,但这是另一个问题。

If there are more than coreSize 100 * queueSize 20 tasks, the number of thread will increase until it hits max size.

我不确定数字 20 是从哪里来的。在您的代码中,队列大小为 Integer.MAX_SIZE,因此在启动超过核心大小的其他线程之前,您必须排队超过 Integer.MAX_SIZE

But the problem is, lets say everything's done and there are no more tasks, the number of threads would not decrease.

线程数将减少到核心线程数。正如@debaicai 提到的,您可以设置 threadPool.allowCoreThreadTimeOut(true) 让核心线程也超时。顺便说一句,1 秒似乎是一个非常低的超时数,但也许这对您的应用程序有意义。

Next, how to make the Executor queue the extras to run later?

临时演员?好吧,您当然应该考虑将阻塞队列的大小限制在更合理的范围内。您可能想看看我针对 growing a thread pool before enqueuing.

的解决方案