JUC源碼分析-線程池篇(三)ScheduledThreadPoolExecutor

JUC源碼分析-線程池篇(三)ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor。它主要用來在給定的延遲以後運行任務,或者按期執行任務。ScheduledThreadPoolExecutor 的功能與 Timer 相似,但 Timer 對應的是單個後臺線程,而 ScheduledThreadPoolExecutor 能夠在構造函數中指定多個對應的後臺線程數。java

  1. JUC源碼分析-線程池篇(三)Timer

1. ScheduledThreadPoolExecutor 簡介

1.1 Timer 和 ScheduledThreadPoolExecutor 區別

Timer ScheduledThreadPoolExecutor
單線程 多線程
單個任務執行時間影響其餘任務調度 多線程,不會影響
基於絕對時間 基於相對時間
一旦執行任務出現異常不會捕獲,其餘任務得不到執行 多線程,單個任務的執行不會影響其餘線程

1.2 ScheduledThreadPoolExecutor 執行流程

ScheduledThreadPoolExecutor 的結構和 Timer 相似,也是由 DelayedWorkQueue、ThreadPoolExecutor、ScheduledFutureTask 三部分組成。DelayedWorkQueue 是一個無界隊列,因此 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中沒有什麼意義(設置 maximumPoolSize 的大小沒有什麼效果)。數據結構

ScheduledThreadPoolExecutor 的執行主要分爲兩大部分。多線程

1)當調用 ScheduledThreadPoolExecutor#scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay() 方法時,會向 ScheduledThreadPoolExecutor#DelayedWorkQueue 添加一個實現了 RunnableScheduledFutur 接口的 ScheduledFutureTask。函數

2)線程池中的線程從 DelayedWorkQueue 中獲取 ScheduledFutureTask,而後執行任務。源碼分析

ScheduledThreadPoolExecutor執行流程

2. ScheduledThreadPoolExecutor 源碼分析

2.1 數據結構

ScheduledThreadPoolExecutor類結構

2.2 定時任務調度 schedule

schedule、scheduleAtFixedRate、scheduleWithFixedDelay 只是將任務設置執行時間後添加到線程池隊列中去了。線程

ublic 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;
}

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
        long initialDelay, long delay, TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    if (delay <= 0)
        throw new IllegalArgumentException();
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command, null,
            triggerTime(initialDelay, unit), unit.toNanos(-delay));
    RunnableScheduledFuture<Void> t = decorateTask(command, sft);
    sft.outerTask = t;
    delayedExecute(t);
    return t;
}

2.3 任務執行 ScheduledFutureTask#run

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);   // 從新添加到任務隊列中
    }
}

參考:code

  1. 《深刻理解Java線程池:ScheduledThreadPoolExecutor》:https://www.jianshu.com/p/925dba9f5969

天天用心記錄一點點。內容也許不重要,但習慣很重要!blog

相關文章
相關標籤/搜索