关注公众号 不爱总结的麦穗 将不定期推送技术好文
本文主要分享支持周期性任务调度的线程池ScheduledThreadPoolExecutor,而对于ScheduledThreadPoolExecutor的应用也可以看看我们在前面一段时间写过的一遍关于SpringBoot动态定时任务的文章玩转SpringBoot动态定时任务(启动、暂停)
介绍
ScheduledThreadPoolExecutor继承ThreadPoolExecutor来重用线程池的功能
ScheduledThreadPoolExecutor 内部构造了两个内部类 ScheduledFutureTask
和 DelayedWorkQueue
:
-
ScheduledFutureTask
: ScheduledThreadPoolExecutor使用专门的任务类型ScheduledFutureTask 来执行周期任务,它继承了FutureTask,还分别实现了Runnable、Future、Delayed接口,说明它是一个可以延迟执行的异步运算任务。 -
DelayedWorkQueue
: 这是 ScheduledThreadPoolExecutor 为存储周期或延迟任务专门定义的一个延迟队列。它内部只允许存储 RunnableScheduledFuture 类型的任务。
源码解析
ScheduledFutureTask内部类
构造函数
private class ScheduledFutureTask<V>
extends FutureTask<V> implements RunnableScheduledFuture<V> {
/** 顺序编号,当两个任务有相同的延迟时间时,按照 FIFO 的顺序入队*/
private final long sequenceNumber;
/** 下次任务执行时的时间 */
private long time;
/** 执行周期时间*/
private final long period;
/** 重新入队的任务*/
RunnableScheduledFuture<V> outerTask = this;
/** 延迟队列的索引 */
int heapIndex;
ScheduledFutureTask(Runnable r, V result, long ns) {
super(r, result);
this.time = ns;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
ScheduledFutureTask(Runnable r, V result, long ns, long period) {
super(r, result);
this.time = ns;
this.period = period;
this.sequenceNumber = sequencer.getAndIncrement();
}
ScheduledFutureTask(Callable<V> callable, long ns) {
super(callable);
this.time = ns;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
ScheduledFutureTask继承自FutureTask
,可以通过返回Future对象来获取执行的结果,将 Runnable/Callable 封装为 ScheduledFutureTask。
run方法
public void run() {
// 是否为周期任务
boolean periodic = isPeriodic();
// 当前线程池运行状态下如果不可以执行任务,取消该任务
if (!canRunInCurre