ScheduledThreadPoolExecutor原理
关注可以查看更多粉丝专享blog~
内部变量period
- period == 0,则为一次性任务。
- period < 0,则为fixed-delay,固定延时的定时可重复执行任务。
- period > 0,则为fixed-rate,固定频率的定时可重复执行任务。
一次性任务
public ScheduledFuture<?> schedule(Runnable command,
long delay,
TimeUnit unit) {
// 参数校验
if (command == null || unit == null)
throw new NullPointerException();
// 构造任务
RunnableScheduledFuture<?> t = decorateTask(command,
new ScheduledFutureTask<Void>(command, null,
triggerTime(delay, unit)));
// 添加任务到延时队列,
delayedExecute(t);
return t;
}
private void delayedExecute(RunnableScheduledFuture<?> task) {
// 状态为shutdown则执行拒绝策略
if (isShutdown())
reject(task);
else {
// 添加任务到延时队列
super.getQueue().add(task);
// 再次判断状态,期间可能有其他线程执行了shutdown操作,如果是shutdown则中断任务并移出队列
if (isShutdown() &&
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task))
task.cancel(false);
else
ensurePrestart();
}
}
// 确保至少一个线程在处理任务
// 1、如果工作线程数小于核心线程数则增加核心线程数
// 2、如果工作线程数 == 0,则启动一个线程
void ensurePrestart() {
int wc = workerCountOf(ctl.get());
if (wc < corePoolSize)
addWorker(null, true);
else if (wc == 0)
addWorker(null, false);
}
ScheduledFutureTask重写了 DelayQueue 的getDelay和compareTo方法
周期性任务
任务会一直运行直到任务中抛出异常/被取消/关闭线程池。
- scheduleWithFixedDelay,固定延时的定时可重复执行任务,上一个任务执行完之后 + period = 下一次执行的时间。
- scheduleWithFixedRate,固定频率的定时可重复任务,上一个任务无论有没有执行完下一次任务都会以initdelday + n * period启动任务,但是 不会并发执行,知道当前任务执行完毕之后再执行。
run()方法
public void run() {
// 是否为周期性任务 isPeriodic(): return period != 0;
boolean periodic = isPeriodic();
// 不是则检查是否可以取消
if (!canRunInCurrentRunState(periodic))
cancel(false);
// 非周期性任务执行run方法,super is FutureTask
else if (!periodic)
ScheduledFutureTask.super.run();
// 周期性任务执行runAndReset(),super is FutureTask
else if (ScheduledFutureTask.super.runAndReset()) {
// 设置下一次运行时间
setNextRunTime();
// 重新执行当前任务(入队DelayQueue)
reExecutePeriodic(outerTask);
}
}
// 是否可以取消executeExistingDelayedTasksAfterShutdown默认为true,如果调用shutdown之后可继续执行
boolean canRunInCurrentRunState(boolean periodic) {
return isRunningOrShutdown(periodic ?
continueExistingPeriodicTasksAfterShutdown :
executeExistingDelayedTasksAfterShutdown);
}
// 一次性任务ScheduledFutureTask.super.run();
public void run() {
// 状态不为NEW或者执行线程不是当前线程则return
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
// 再次判断是否为NEW,可能被中断(能够执行到此处的只有一个线程,因为CAS只有一个线程可以设置成功)
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// 执行任务
result = c.call();
ran = true;
} catch (Throwable ex) {
// 出现异常则设置状态为EXCEPTION
result = null;
ran = false;
setException(ex);
}
// 成功则设置结果
if (ran)
set(result);
}
} finally {
// 运行器必须为非null,直到状态稳定下来,防止并发调用run()
runner = null;
// 必须在将运行器归零之后重新读取状态,以防止泄漏中断
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
// 周期性任务ScheduledFutureTask.super.runAndReset();
protected boolean runAndReset() {
// 状态不为NEW或者执行线程不是当前线程则return
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
// 再次判断是否为NEW,可能被中断(能够执行到此处的只有一个线程,因为CAS只有一个线程可以设置成功)
if (c != null && s == NEW) {
try {
// 执行任务,不设置结果
c.call();
ran = true;
} catch (Throwable ex) {
setException(ex);
}
}
} finally {
// 运行器必须为非null,直到状态稳定下来,防止并发调用run()
runner = null;
// 必须在将运行器归零之后重新读取状态,以防止泄漏中断
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
// 返回执行结果如果成功则设置任务状态为NEW
return ran && s == NEW;
}