普通的线程池执行流程,应该很多人都知道了,可是定时任务线程更为重要,很多框架都用到了,应用场景有很多,比如心跳,拉取信息,redisson锁的续约,同步数据等
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
//shutdown后是否继续执行定时任务
private volatile boolean continueExistingPeriodicTasksAfterShutdown;
//shutdown后是否继续执行延迟任务
private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
//cancle方法收费需要将该任务从队列移除
private volatile boolean removeOnCancel = false;
//任务的序列号
private static final AtomicLong sequencer = new AtomicLong();
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
unit.toNanos(period));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
return t;
}
ScheduledFutureTask
public void run() {
//判断任务是否周期执行
boolean periodic = isPeriodic();
//检查当前状态能否执行任务
if (!canRunInCurrentRunState(periodic))
cancel(false);
//非周期任务直接执行,只执行一次
else if (!periodic)
ScheduledFutureTask.super.run();
//周期任务的执行
else if (ScheduledFutureTask.super.runAndReset()) {
//设置下一次执行任务时间
setNextRunTime();
//任务的下一次执行
reExecutePeriodic(outerTask);
}
}
//没做什么事情,留给后面的扩展点
protected <V> RunnableScheduledFuture<V> decorateTask(
Runnable runnable, RunnableScheduledFuture<V> task) {
return task;
}
private void delayedExecute(RunnableScheduledFuture<?> task) {
//校验线程池状态,如果已经停止,则拒绝
if (isShutdown())
reject(task);
else {
//加入队列
super.getQueue().add(task);
//再次检查,线程池状态发生变化,不能够执行,移出队列,取消任务
if (isShutdown() &&
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task))
task.cancel(false);
else
//开启线程
ensurePrestart();
}
}
DelayedWorkQueue,阻塞获取头结点
public RunnableScheduledFuture<?> take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture<?> first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
first = null; // don't retain ref while waiting
if (leader != null)
//已经存在leader线程,当前线程await阻塞
available.await();
else {
//当前线程作为leader线程,并制定头结点的延迟时间作为阻塞时间
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
//leader线程没有阻塞,可以找到头结点,唤醒阻塞线程
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
//根据前面设置的时间,跟当前时间比较,计算要等待的时间
public long getDelay(TimeUnit unit) {
return unit.convert(time - now(), NANOSECONDS);
}
//进行按时间排序,形成一个小顶堆
private void siftUp(int k, RunnableScheduledFuture<?> key) {
while (k > 0) {
int parent = (k - 1) >>> 1;
RunnableScheduledFuture<?> e = queue[parent];
if (key.compareTo(e) >= 0)
break;
queue[k] = e;
setIndex(e, k);
k = parent;
}
queue[k] = key;
setIndex(key, k);
}