JDK源碼分析-ScheduledExecutorService

  • 2019 年 10 月 7 日
  • 筆記

概述

介面的繼承結構如下:

下面分析這幾個介面的定義。

Executor

從名字來看,Executor 可譯為「執行器」,它的作用就是執行任務。該介面只有一個 execute 方法:

public interface Executor {      // 執行給定的任務(Runnable)      void execute(Runnable command);  }

該方法的作用就是(在將來的某個時間)執行給定的命令,即實現了 Runnable 介面的對象。該命令可能在一個新的執行緒中執行,也可能在調用它的執行緒中執行。它的用法示例程式碼如下:

Executor executor = ...;  executor.execute(new RunnableTask1());  executor.execute(new RunnableTask2());

PS: 前文分析的執行緒池類「JDK源碼分析-ThreadPoolExecutor」就是該介面的一個實現類。

ExecutorService

ExecutorService 可理解為「執行器服務」,它繼承自 Executor 介面,是對 Executor 的擴展,定義如下:

public interface ExecutorService extends Executor {      // 關閉執行器服務。在此過程中之前提交的任務會執行,但不接收新的任務。若已關閉則無效。      void shutdown();        // 嘗試停止所有正在執行的任務,並返回等待執行的任務列表      List<Runnable> shutdownNow();        // 是否已關閉      boolean isShutdown();        // 是否已終止      boolean isTerminated();        // 阻塞,直到所有任務都在 shutdown 請求之後執行完畢,或者超時發生,或者當前執行緒被中斷(以先發生的情況為準)      boolean awaitTermination(long timeout, TimeUnit unit)          throws InterruptedException;        // 提交一個 Callable 任務,有返回值      <T> Future<T> submit(Callable<T> task);        // 提交一個 Runnable 任務,有返回值(執行成功後返回 result 值)      <T> Future<T> submit(Runnable task, T result);        // 提交一個 Runnable 任務,有返回值(執行成功後返回 null)      Future<?> submit(Runnable task);        // 執行提交的 Callable 任務列表,並返回對應的 Future 結果(即批量執行任務)      <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)          throws InterruptedException;        // 與上述方法類似,多了超時等待。若任務超時則完不成      <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,                                    long timeout, TimeUnit unit) throws InterruptedException;        // 執行提交的 Callable 任務列表,返回已成功執行的任務的結果(無異常),若有的話。      <T> T invokeAny(Collection<? extends Callable<T>> tasks)          throws InterruptedException, ExecutionException;        // 與上述方法類似,多了超時等待      <T> T invokeAny(Collection<? extends Callable<T>> tasks,                      long timeout, TimeUnit unit)          throws InterruptedException, ExecutionException, TimeoutException;  }

該介面與 Executor 相比,主要增加了有返回值的提交任務的方法。

PS: 可參考前文執行緒池 ThreadPoolExecutor 的相關分析;有關 Future 介面,前面「JDK源碼分析-FutureTask」也已分析,這裡不再贅述。

ScheduledExecutorService

ScheduledThreadPoolExecutor 介面繼承自 ExecutorService 介面,該介面定義了延遲執行的方法和周期性執行的方法,如下:

public interface ScheduledExecutorService extends ExecutorService {      // 創建一次性操作(Runnable),該操作會在指定的延遲之後執行(其實就是創建了一個定時任務)      public ScheduledFuture<?> schedule(Runnable command,                                         long delay, TimeUnit unit);        // 與上述方法類型,參數類型不同(Callable)      public <V> ScheduledFuture<V> schedule(Callable<V> callable,                                             long delay, TimeUnit unit);        /*       * 創建並執行一個周期性的任務       * 執行時間分別為 initialDelay, initialDelay + period, initialDelay + 2*period, 以此類推       * 若有異常則停止後續的執行;若任務執行時間超過其周期,則後續執行會延遲開始       */      public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,                                                    long initialDelay,                                                    long period,                                                    TimeUnit unit);        /*       * 創建並執行一個周期性的任務       * 該操作在給定的初始延遲之後首先啟用,然後在一次執行結束和下一次執行開始之間使用給定的延遲。       * 該方法與上述有些易混淆,不同的地方在於:       *      上述方法是以每次開始執行的時間來計算;       *      而本方法是以每次執行結束的時間和下次開始執行的時間計算       */      public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,                                                       long initialDelay,                                                       long delay,                                                       TimeUnit unit);  }

ScheduledExecutorService 可以做一些延遲執行的任務,或者周期性執行的任務,它在 JDK 中有一個實現類 ScheduledThreadPoolExecutor,後文再進行分析。

小結

本文主要分析了 Executor、ExecutorService 和 ScheduledExecutorService 這三個介面,它們之間是繼承關係,主要都是圍繞「執行任務」這個核心來的:

1. Executor 只有一個 execute 方法,只能執行 Runnable 任務,且無返回值;

2. ExecutorService 增強了 Executor 的功能,主要包括可以提交 Callable 任務,且有返回值;

3. ScheduledExecutorService 進一步增強了 ExecutorService 的功能,增加了延遲執行任務和周期性執行任務的功能。