ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。它的功能与 Timer 类似,但其功能更强大、更灵活。Timer 对应的是单个后台线程,而 ScheduledThreadPoolExecutor 可以在构造函数中指定多个对应的后台线程数。
ScheduledThreadPoolExecutor 的运行机制
ScheduledThreadPoolExecutor 的执行示意图如下所示
DelayQueue 是一个无界队列,所以 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中没有什么意义。
ScheduledThreadPoolExecutor 的执行主要分为两大部分。
- 当调用 ScheduledThreadPoolExecutor 的 scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay() 方法时,会向 ScheduledThreadPoolExecutor 的 DelayQueue 添加一个实现了 RunnableScheduleFutur 接口的 ScheduleFutureTask。
- 线程池中的线程从 DelayQueue 中获取 ScheduleFutureTask,然后执行任务。
ScheduledThreadPoolExecutor 的实现
ScheduleFutureTask 主要包含3个成员变量
- long 型成员变量 time,表示这个任务将要被执行的时间
- long 型成员变量 sequenceNumber,表示这个任务被添加到 ScheduledThreadPoolExecutor 中的序号
- long 型成员变量 period,表示执行任务的间隔周期
DelayQueue 封装了一个 PriorityQueue,它会对队列中的 ScheduleFutureTask 进行排序。排序时,time 小的排在前面。如果两个 task 的 time 相同,那就比较 sequenceNumber,小的排在前面。
首先我们看看 ScheduledThreadPoolExecutor 中的线程执行周期任务的过程。
- 线程1从 DelayQueue 中获取已到期的 ScheduleFutureTask。到期任务是指 ScheFutuTask 的 time 大于等于当前时间
- 线程1执行这个 ScheFutureTask
- 线程1修改 ScheduleFutureTask 的 time 变量为下次要被执行的时间
- 线程1把这个修改 time 之后的 ScheduleFutureTask 放回 DelayQueue 中