为什么 ScheduledThreadPoolExecutor 的队列大小总是 0?

Why is the queue size of a ScheduledThreadPoolExecutor always 0?

我正在使用 ScheduledThreadPoolExecutor 每毫秒安排一个任务。据我了解,ScheduledThreadPoolExecutor 在内部使用无界队列,并在 none 线程可用于执行任务时附加任务。

因此,我假设如下:如果我有一个单线程的执行程序,并且周期性 运行 的任务花费的时间比计划的频率长,那么队列大小会增加不断地。尽管对于我的以下最小代码示例,这似乎并不正确:

import java.util.concurrent.{ScheduledThreadPoolExecutor, TimeUnit}

object MinimalExample {

  val numberOfThreads = 1
  val executor = new ScheduledThreadPoolExecutor(numberOfThreads)

  def execute(): Unit = {
    val thread = new TestThread(executor)
    val initialDelay = 0
    val interval = 1
    executor.scheduleAtFixedRate(thread, initialDelay, interval, TimeUnit.MILLISECONDS)
  }

  def main(args: Array[String]): Unit = {
    execute()
  }
}

class TestThread(executor: ScheduledThreadPoolExecutor) extends Runnable {
  override def run(): Unit = {
    Thread.sleep(2000)
    println("just slept 2 seconds")
    println(s"queue size: ${executor.getQueue().size()}")
  }
}

队列的大小总是打印0。如果任务需要超过 2 秒并且每毫秒安排一次,那怎么可能呢?我错过了什么吗?

在执行周期性任务时,它会从内部队列中删除(take()-n 或 poll()-ed)。当任务成功完成后,它会在稍后重新添加。 (如果它抛出异常,则不会。)这适用于 scheduleWithFixedDelayscheduleAtFixedRategetQueue returns 内部任务队列 正在等待 执行。该队列还包含等待延迟到期的延迟任务,但不包含当前正在执行的任务。 (使用 getActiveCount 查询。)

引用 scheduleAtFixedRate 的 javadoc:

If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

这是通过仅在周期性任务执行后将其重新添加到队列中来完成的。任务本身在执行期间不会出现在队列中,并且永远不会出现在队列中多次。