除非队列已满,否则固定大小线程池中同时 运行 个线程的计数是否总是小于 corePoolSize?

Will the count of simultaneously running thread in a fixed-size thread pool be always less than corePoolSize unless the queue is full?

javadoc 说:

When a new task is submitted [...], and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full. By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks.

这是否意味着固定大小线程池中同时运行个线程的数量将永远少于corePoolSize除非队列已满?

Does it mean that the count of simultaneously running thread in a fixed-size thread pool will be always less than corePoolSize unless the queue is full?

不,不是。

语义方法

在我阅读它时,对于固定大小的池,此引用没有说明活动线程的数量,特别是与队列大小相关的内容。唯一将两者联系起来的一句话是:

If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.

这不适用,因为在固定大小的池中 corePoolSize 等于 maximumPoolSize。 "if" 条件从未满足。

虽然它声明的是:

When a new task is submitted [...], and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.

只要未达到 corePoolSize 限制,就会创建线程。只要未达到此限制,线程就不会被重用(但它们 可能 因未捕获的异常或通过池的超时功能而死亡)。如果我们足够快地创建它们或有足够长的队列,这显然为创建 corePoolSize 个线程留出了空间。

实验方法

这些知识让我们可以想象这样的场景:创建一个大小为 2 的固定池,等待队列大小为 5,然后向池中提交两个长 运行 任务。 ("Long running" 意味着每个任务的执行时间比主线程提交它们所花费的时间以及线程池确认它们的存在并处理它们所花费的时间大一个数量级)。一个可能的时间表如下:

  1. 主线程将任务 T1 提交到新的空池
  2. 根据上面的引用,corePoolSize还没有被命中,创建一个新的线程来执行T1。
  3. 线程1开始执行T1
  4. 主线程提交T2
  5. 与步骤 2 一样,生成第二个线程,池达到 corePoolSize
  6. 同步骤3,第二个线程开始执行任务T2

此时,线程池有一个空队列,运行 线程计数正好是 corePoolSize,而不是 "under corePoolSize",QED。

这是什么意思:

反过来说,这意味着获得线程数大于 corePoolSize 的唯一方法是同时满足所有条件:

  1. 运行 个线程数大于(或等于)corePoolSize,并且
  2. maximumPoolSize 大于 corePoolSize,并且
  3. 已满队列