ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor。它主要用來在給定的延遲以後運行任務,或者按期執行任務。ScheduledThreadPoolExecutor 的功能與 Timer 相似,但 Timer 對應的是單個後臺線程,而 ScheduledThreadPoolExecutor 能夠在構造函數中指定多個對應的後臺線程數。java
Timer | ScheduledThreadPoolExecutor |
---|---|
單線程 | 多線程 |
單個任務執行時間影響其餘任務調度 | 多線程,不會影響 |
基於絕對時間 | 基於相對時間 |
一旦執行任務出現異常不會捕獲,其餘任務得不到執行 | 多線程,單個任務的執行不會影響其餘線程 |
ScheduledThreadPoolExecutor 的結構和 Timer 相似,也是由 DelayedWorkQueue、ThreadPoolExecutor、ScheduledFutureTask 三部分組成。DelayedWorkQueue 是一個無界隊列,因此 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中沒有什麼意義(設置 maximumPoolSize 的大小沒有什麼效果)。數據結構
ScheduledThreadPoolExecutor 的執行主要分爲兩大部分。多線程
1)當調用 ScheduledThreadPoolExecutor#scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay() 方法時,會向 ScheduledThreadPoolExecutor#DelayedWorkQueue 添加一個實現了 RunnableScheduledFutur 接口的 ScheduledFutureTask。函數
2)線程池中的線程從 DelayedWorkQueue 中獲取 ScheduledFutureTask,而後執行任務。源碼分析
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; }
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
天天用心記錄一點點。內容也許不重要,但習慣很重要!blog