Davids原理探究:ScheduledThreadPoolExecutor原理

ScheduledThreadPoolExecutor原理

关注可以查看更多粉丝专享blog~

ScheduledThreadPoolExecutor状态

内部变量period

  1. period == 0,则为一次性任务。
  2. period < 0,则为fixed-delay,固定延时的定时可重复执行任务。
  3. 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方法
ScheduledFutureTask类图

周期性任务

任务会一直运行直到任务中抛出异常/被取消/关闭线程池

  1. scheduleWithFixedDelay,固定延时的定时可重复执行任务,上一个任务执行完之后 + period = 下一次执行的时间。
  2. 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章