我正在使用ScheduledThreadPoolExecutor
每毫秒安排一项任务。据我所知,ScheduledThreadPoolExecutor
在内部使用无界队列,并在没有任何线程可用于执行时附加任务。
结果我假设如下:如果我有一个具有单个线程的执行程序,并且定期运行的任务所花费的时间比调度的频率长,那么队列大小会不断增加。不知何故,这似乎不正确,但我的下面的最小代码示例:
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秒并且每毫秒安排一次,那怎么可能呢?我错过了什么吗?
答案 0 :(得分:2)
在执行定期任务时,将从内部队列中将其删除(resources :payments do
get 'pay', on: :member
end
-n或take()
-ed)。任务成功完成后,将重新添加它。 (或者,如果引发异常,则不会。)这同时适用于poll()
和scheduleWithFixedDelay
。 scheduleAtFixedRate
返回内部任务等待的队列。此队列还包含等待其延迟到期的延迟任务,但不包含当前正在执行的任务。 (使用getQueue
进行查询。)
将Javadoc引用为getActiveCount
:
如果此任务的执行时间超过其执行时间,则随后的执行可能会 late 开始,但不会同时执行。
这是通过仅在执行之后将定期任务重新添加到队列中来完成的。任务本身在执行期间不会出现在队列中,也不会多次出现在队列中。