AbstractExecutorService 筆記

介紹

AbstractExecutorService 是 JDK 線程池 ThreadPoolExecutor,ForkJoinPool 等的父類,提供了許多非常有用的功能。

AbstractExecutorService 的繼承關係如下:
繼承關係

Executor

Executor 是執行 Runnable 任務的接口,用於解耦任務創建和任務執行,包括線程的使用和執行的排期等。在需要創建多個線程執行任務時,Executor 還可以代替 new Thread(new(RunnableTask())).start(),而使用

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

然而 Executor 並不要求任務按照異步的方式執行,也可以只是使用當前線程執行任務,比如:

class DirectExecutor implements Executor {
  public void execute(Runnable r) {
    r.run();
  }
}

但是 Executor 的實現類一般來說都是使用異步的方式執行提交的任務,如下:

class ThreadPerTaskExecutor implements Executor {
  public void execute(Runnable r) {
    new Thread(r).start();
  }
}

Executor 接口方法定義如下:

/**
 *
 * 在接下來的某個時刻執行任務。根據實現類的不同,任務可能在調用方的線程中執行,也可能創建一個新的線程執行,或者在一個線程池中執行。
 *
 * @param command the runnable task 可執行的任務(實現 Runnable 接口的對象)
 * @throws RejectedExecutionException if this task cannot be
 * accepted for execution 如果 Executor 不接受任務則拋出該異常
 * @throws NullPointerException if command is null 如果任務爲爲空則拋出該異常
 */
void execute(Runnable command);

ExecutorService

ExecutorService 提供一些方法用於管理服務終止以及提供一些返回計算結果(Future) 的執行任務的方法。Future(計算結果)可以用於跟蹤異步任務的執行結果,查看是否完成,取消未完成的任務等。

ExecutorService 可以被關閉。被關閉的 ExecutorService 無法再執行異步任務。ExecutorService 提供了兩個關閉 ExecutorService 的方法:

  1. shutdown:該方法會繼續執行在調用該方法前提交的任務,但是會拒絕之後提交的任務。在之前提交的任務全部結束後關閉 ExecutorService。
  2. shutdownNow: 該方法會暫停正在進行中和等待中的任務。

ExecutorService 如果未在使用,那麼應該關閉回收計算機資源。

ExecutorService 提供 submit 方法,用於擴展 execute。submit 能夠返回一個 Future。invokeAny 和 invokeAll 能夠處理一批的任務,並等待一個或者所有的異步任務完成。

ExecutorService 使用例子:

class NetworkService implements Runnable {
    private final ServerSocket serverSocket;
    private final ExecutorService pool;

    public NetworkService(int port, int poolSize)
        throws IOException {
      serverSocket = new ServerSocket(port);
      pool = Executors.newFixedThreadPool(poolSize);
    }

    public void run() { // run the service
      try {
        for (;;) {
          pool.execute(new Handler(serverSocket.accept()));
        }
      } catch (IOException ex) {
        pool.shutdown();
      }
    }
  }

  class Handler implements Runnable {
    private final Socket socket;
    Handler(Socket socket) { this.socket = socket; }
    public void run() {
      // read and service request on socket
    }
  }

關停 ExecutorService 的例子:

void shutdownAndAwaitTermination(ExecutorService pool) {
    //  拒接接受新任務
    pool.shutdown();
    try {
      // 如果服務在 60 秒還未關停則做更多的處理
      if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
        //立即關停所有任務
        pool.shutdownNow();
        // 如果服務在 60 秒還未關停則輸出提示
        if (!pool.awaitTermination(60, TimeUnit.SECONDS))
            System.err.println("Pool did not terminate");
      }
    } catch (InterruptedException ie) {
      // 如果遇到線程中斷異常那麼立即關停服務並將線程置爲中斷狀態
      pool.shutdownNow();
      Thread.currentThread().interrupt();
    }
  }

ExecutorService 提供的內存一致性保證:提交任務操作一定在線程處理任務之前完成,並且線程處理任務一定在 Future.get()獲取到異步任務結果前完成。

方法定義

/**
 * 開始關停 ExecutorService。
 * 關停前提交的任務會繼續執行,但是不會接受新任務。如果是已經關停的 ExecutorService 調用該方法不會發生任何變換。
 *
 * @throws SecurityException 如果存在安全管理器並且關閉線程沒有權限修改線程狀態,那麼會拋出該異常。沒有權限修改的原因是沒有獲得 RuntimePermission 或者是安全管理器檢查訪問權限時校驗未通過。
 */
void shutdown();

/**
 * 立即關停 ExecutorService
 * 嘗試關停所有進行中的任務,同時拒絕任何新任務,停止處理等待中的任務,並且返回等待任務的列表。
 * 正在進行中的任務沒法保證一定成功停止,比如通過線程中斷方法(Thread.interrupt)中斷進行中的任務,而任務沒有響應線程中斷,那麼任務無法終止。
 *
 * @return 正在進行中的任務列表
 * @throws SecurityException 如果存在安全管理器並且關閉線程沒有權限修改線程狀態,那麼會拋出該異常。沒有權限修改的原因是沒有獲得 RuntimePermission 或者是安全管理器檢查訪問權限時校驗未通過。
 */
List<Runnable> shutdownNow();

/**
 * 返回關閉狀態:如果關閉則返回 true,否則返回 false
 *
 * @return 關閉狀態:如果關閉則返回 true,否則返回 false
 */
boolean isShutdown();

/**
 * 如果關閉後所有任務都完成那麼返回 true
 *
 * @return 如果關閉後所有任務都完成那麼返回 true
 */
boolean isTerminated();

/**
 * 當關閉 ExecutorService 之後用於阻塞等待給定的時間,讓正在進行中的任務完成,直到任意條件滿足:
 * 1. 所有任務都已經完成
 * 2. 等待超時
 * 3. 線程被中斷
 *
 * @param 等待的時間
 * @param unit the time unit of the timeout argument 時間單位
 * @return 如果 ExecutorService 在時間內終止了那麼返回 true,否則返回 false
 * @throws InterruptedException 當前線程被中斷拋出中斷異常
 */
boolean awaitTermination(long timeout, TimeUnit unit)
    throws InterruptedException;

/**
 * 提交一個可執行的並且由返回值的任務,並返回一個任務執行結果(Future)。
 * 如果希望立即阻塞直到獲取異步任務結果可以使用 result = exec.submit(aCallable).get()。Future.get()或阻塞直到獲取到異步任務結果。
 * ExecutorService 提供了很多方法用於將閉包對象轉成被執行的方法。
 *
 * @param 可被 ExecutorService 執行的任務
 * @param <T> 任務的執行結束後返回的結果的對象類型
 * @return 可以跟蹤異步任務執行結果的對象(Future)
 * @throws RejectedExecutionException 如果 ExecutorService 拒絕任務則拋出
 * @throws NullPointerException if the task is null
 */
<T> Future<T> submit(Callable<T> task);

/**
 * 提交一個可執行的任務,並指定任務返回的對象類型,該方法返回一個可以跟蹤任務執行結果(Future)
 * @param task 可執行的任務
 * @param Result 該任務執行後返回的類型
 * @param <T>任務的執行結束後返回的結果的對象類型
 * @return 任務執行結果(Future)
 * @throws RejectedExecutionException ExecutorService 拒絕任務後拋出該異常
 * @throws NullPointerException 如果任務(task)是 null 拋出該異常
 */
<T> Future<T> submit(Runnable task, T result);

/**
 * 提交一個可執行的任務,並返回一個可以跟蹤任務執行結果的對象(Future)
 *
 * @param task 可執行的任務
 * @return 任務執行結果(Future)
 * @throws RejectedExecutionException 如果 ExecutorService 拒絕該任務則拋出該異常
 * @throws NullPointerException 如果提交了一個空任務則拋出該異常
 */
Future<?> submit(Runnable task);

/**
 * 執行批量任務並返回跟蹤這批任務執行結果的對象集合(List<Future>)
 * 該方法會阻塞等待任務結束後纔將結果返回,所以調用方拿到結果時,任務已經結束(或者任務執行過程中斷導致的異常結束)。
 * 如果在 invokeAll 執行期間改變任務集合可能會引發未定義方法說明上(throws 定義的異常列表)的異常。
 * 比如 invokeAll 使用 for 循環遍歷集合時集合被刪除元素拋出 ConcurrentModificationException 異常。
 *
 * @param tasks 任務集合
 * @param <T> 任務類型
 * @return 任務執行結果(Future)集合
 * @throws InterruptedException 如果在等待結果過程中線程被中斷則拋出該異常
 * @throws NullPointerException 如果任務結合是空對象則拋出該異常
 * @throws RejectedExecutionException 如果任務提交被拒絕則拋出該異常
 */
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    throws InterruptedException;

/**
 * 在上一個 invokeAll 基礎上增加了等待時間。
 *
 * @param tasks 任務集合
 * @param timeout 等待時間
 * @param unit 時間單位
 * @param <T> 任務完成後返回類型
 * @throws InterruptedException 如果在等待過程中線程被中斷則拋出該異常
 * @throws NullPointerException 如果提交的任務集合是空對象則拋出該異常
 * @throws RejectedExecutionException 如果本次提交被拒絕則拋出該異常
 */
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                              long timeout, TimeUnit unit)
    throws InterruptedException;

/**
 * 執行給定任務列表中的任一任務。
 * 如果有任一任務執行完成則將該任務執行結果返回,並且取消其他任務。
 *
 * @param tasks 任務集合
 * @param <T> 任務返回的類型
 * @return 任務執行結果(Future)
 * @throws InterruptedException 如果等待過程中線程被中斷則拋出中斷異常
 * @throws NullPointerException 如果提交的任務
 * @throws IllegalArgumentException 如果任務是空列表則拋出該異常
 * @throws ExecutionException 如果沒有任何任務執行成功則拋出該異常
 * @throws RejectedExecutionException 如果任務被拒絕則拋出該異常
 */
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
    throws InterruptedException, ExecutionException;

/**
 * 在上一個 invokeAny 基礎上增加等待時間
 *
 * @param tasks the collection of tasks
 * @param timeout the maximum time to wait
 * @param unit the time unit of the timeout argument
 * @param <T> the type of the values returned from the tasks
 * @return the result returned by one of the tasks
 * @throws InterruptedException if interrupted while waiting
 * @throws NullPointerException if tasks, or unit, or any element
 *         task subject to execution is {@code null}
 * @throws TimeoutException if the given timeout elapses before
 *         any task successfully completes
 * @throws ExecutionException if no task successfully completes
 * @throws RejectedExecutionException if tasks cannot be scheduled
 *         for execution
 */
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
                long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;

CompletionService

CompletionService 用於給創建異步任務和消費異步任務結果解耦。CompletionService 依賴 Executor 執行異步任務,而自己管理完成隊列,維護異步任務執行結果。

/**
 * 提交任務
 *
 * @param task 任務
 * @return 任務執行結果(Future)
 * @throws RejectedExecutionException 如果拒絕任務則拋出該異常
 * @throws NullPointerException 如果任務是空對象則拋出該異常
 */
Future<V> submit(Callable<V> task);

/**
 * 同上
 *
 * @param task the task to submit
 * @param result the result to return upon successful completion
 * @return a Future representing pending completion of the task,
 *         and whose {@code get()} method will return the given
 *         result value upon completion
 * @throws RejectedExecutionException if the task cannot be
 *         scheduled for execution
 * @throws NullPointerException if the task is null
 */
Future<V> submit(Runnable task, V result);

/**
 * 獲取計算結果並在隊列中刪除該計算結果。如果沒有任務任務完成,那麼該方法將會阻塞線程等待任務計算結果
 *
 * @return 計算結果
 * @throws InterruptedException 在等待過程中線程被中斷則拋出該異常
 */
Future<V> take() throws InterruptedException;

/**
 * 同 take(),不一樣的地方時該方法不會阻塞,即如果沒有任務完成則返回 null。
 *
 * @return 任務計算結果
 */
Future<V> poll();

/**
 * 通 take(),只是增加了等待超時時間的設置。
 *
 * @param timeout how long to wait before giving up, in units of
 *        {@code unit}
 * @param unit a {@code TimeUnit} determining how to interpret the
 *        {@code timeout} parameter
 * @return the Future representing the next completed task or
 *         {@code null} if the specified waiting time elapses
 *         before one is present
 * @throws InterruptedException if interrupted while waiting
 */
Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;

ExecutorCompletionService

ExecutorCompletionService 是 CompletionService 實現類。ExecutorCompletionService 利用 AbstractExecutorService 構建 RunnableFuture(一個即表示任務又表示計算結果的對象),通過 Executor 提交任務,並在任務直接結束後將計算結果存到阻塞隊列中。

public class ExecutorCompletionService<V> implements CompletionService<V> {
  //任務執行者,用於提交任務
  private final Executor executor;
  // 任務執行服務,用戶構建 RunnableFuture
  private final AbstractExecutorService aes;
  // 阻塞隊列。用於存儲任務的計算結果
  private final BlockingQueue<Future<V>> completionQueue;

  /**
   * 自定義一個計算結果,主要實現完成異步任務時,將計算結果加到阻塞隊列中。
   */
  private class QueueingFuture extends FutureTask<Void> {
      QueueingFuture(RunnableFuture<V> task) {
          super(task, null);
          this.task = task;
      }
      // FutureTask 留了一個鉤子,用於完成任務後執行相關功能。本身 FutureTask 沒有任務實現,這裏將計算結果加到阻塞隊列中。
      protected void done() { completionQueue.add(task); }
      private final Future<V> task;
  }

  // 自定義構建 RunnableFuture
  private RunnableFuture<V> newTaskFor(Callable<V> task) {
      if (aes == null)
          return new FutureTask<V>(task);
      else
          return aes.newTaskFor(task);
  }
  // 自定義構建 RunnableFuture
  private RunnableFuture<V> newTaskFor(Runnable task, V result) {
      if (aes == null)
          return new FutureTask<V>(task, result);
      else
          return aes.newTaskFor(task, result);
  }

  /**
   * 構造方法
   *
   * @param executor the executor to use
   * @throws NullPointerException if executor is {@code null}
   */
  public ExecutorCompletionService(Executor executor) {
      if (executor == null)
          throw new NullPointerException();
      this.executor = executor;
      this.aes = (executor instanceof AbstractExecutorService) ?
          (AbstractExecutorService) executor : null;
      this.completionQueue = new LinkedBlockingQueue<Future<V>>();
  }

  /**
   * 構造方法
   *
   * @param executor the executor to use
   * @param completionQueue the queue to use as the completion queue
   *        normally one dedicated for use by this service. This
   *        queue is treated as unbounded -- failed attempted
   *        {@code Queue.add} operations for completed tasks cause
   *        them not to be retrievable.
   * @throws NullPointerException if executor or completionQueue are {@code null}
   */
  public ExecutorCompletionService(Executor executor,
                                   BlockingQueue<Future<V>> completionQueue) {
      if (executor == null || completionQueue == null)
          throw new NullPointerException();
      this.executor = executor;
      this.aes = (executor instanceof AbstractExecutorService) ?
          (AbstractExecutorService) executor : null;
      this.completionQueue = completionQueue;
  }

  public Future<V> submit(Callable<V> task) {
      if (task == null) throw new NullPointerException();
      RunnableFuture<V> f = newTaskFor(task);
      executor.execute(new QueueingFuture(f));
      return f;
  }

  public Future<V> submit(Runnable task, V result) {
      if (task == null) throw new NullPointerException();
      RunnableFuture<V> f = newTaskFor(task, result);
      executor.execute(new QueueingFuture(f));
      return f;
  }

  public Future<V> take() throws InterruptedException {
      return completionQueue.take();
  }

  public Future<V> poll() {
      return completionQueue.poll();
  }

  public Future<V> poll(long timeout, TimeUnit unit)
          throws InterruptedException {
      return completionQueue.poll(timeout, unit);
  }

AbstractExecutorService

AbstractExecutorService 實現了 ExecutorService 定義的執行任務的方法,比如 submit,invokeAll,invokeAny 等。AbstractExecutorService 提供了一個 newTaskFor 方法用於構建 RunnableFuture 對象。執行任務方法返回的跟蹤任務執行結果的對象都是通過 newTaskFor 來構建的。如果有需要可以通過自定義 newTaskFor 來構建所需的 RunnableFuture。

/**
 * 構建用於跟蹤任務執行結果的對象。
 * 如果有需要可以重寫該方法自定義跟蹤任務結果對象
 *
 * @param runnable 可執行任務
 * @param value 任務執行結果類型
 * @param <T> 任務執行結果的類型
 * @return 任務執行結果
 * @since 1.6
 */
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

/**
 * 同上
 *
 * @param callable the callable task being wrapped
 * @param <T> the type of the callable's result
 * @return a {@code RunnableFuture} which, when run, will call the
 * underlying callable and which, as a {@code Future}, will yield
 * the callable's result as its result and provide for
 * cancellation of the underlying task
 * @since 1.6
 */
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

/**
 * 提交任務
 */
public Future<?> submit(Runnable task) {
    // 校驗任務,如果是空對象則拋出空指針異常
    if (task == null) throw new NullPointerException();
    // 構建一個 RunnableFuture 對象。RunnableFuture 本身表示一個任務(extends Runnable),同時也表示一個任務執行結果(extends Future)。
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    // 執行任務
    execute(ftask);
    // 將 RunnableFuture 對象返回
    return ftask;
}

/**
 * @throws RejectedExecutionException {@inheritDoc}
 * @throws NullPointerException       {@inheritDoc}
 */
public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task, result);
    execute(ftask);
    return ftask;
}

/**
 * @throws RejectedExecutionException {@inheritDoc}
 * @throws NullPointerException       {@inheritDoc}
 */
public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

/**
 * 執行批量任務中的任一任務
 */
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                          boolean timed, long nanos)
    throws InterruptedException, ExecutionException, TimeoutException {
    // 如果任務是空對象拋出空指針異常
    if (tasks == null)
        throw new NullPointerException();
    int ntasks = tasks.size();
    // 如果任務集合是空集合拋出參數不合法異常
    if (ntasks == 0)
        throw new IllegalArgumentException();
    // 構建計算結果集合
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);

    // 任務提交和消費的生產者消費者工具
    ExecutorCompletionService<T> ecs =
        new ExecutorCompletionService<T>(this);

    // 每次提交前都先檢查一下是否有完成的任務,如果完成則直接返回完成任務的計算結果,否則繼續提交剩餘任務

    try {
        //異常信息。用於最後一次獲取的異常信息。如果任務沒有正常結束,將該異常信息拋出。
        ExecutionException ee = null;
        // 等待時間
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        Iterator<? extends Callable<T>> it = tasks.iterator();

       // 先提交一個任務,以後再循環時先檢查是否有任務已經完成。
       // 利用生產者消費者工具提交任務。任務如果結束後,會將計算結果存入到工具的阻塞隊列中。
        futures.add(ecs.submit(it.next()));
        --ntasks;
        int active = 1;

        for (;;) {
            // 檢查是否有任務已經完成,如果有那麼返回任務結果,否則繼續提交任務
            Future<T> f = ecs.poll();
            if (f == null) {
                // 還有任務未提交完,繼續提交任務
                if (ntasks > 0) {
                    --ntasks;
                    futures.add(ecs.submit(it.next()));
                    ++active;
                }
                // 所有任務已執行結束,那麼跳出循環。如果到這應該有執行異常的結果,後續會拋出執行異常
                else if (active == 0)
                    break;
                // 如果設置超時時間,那麼利用阻塞隊列的等待阻塞獲取異常結果。如果超時未獲取到計算結果,那麼拋出超時異常。
                else if (timed) {
                    f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                    if (f == null)
                        throw new TimeoutException();
                    // 正常獲取到結果,那麼繼續更新等待剩餘時間。以防止 f.get()異常後還需要走這段代碼,需要繼續阻塞等待。
                    nanos = deadline - System.nanoTime();
                }
                // 如果沒有設置超時時間,那麼無限等待獲取計算結果
                else
                    f = ecs.take();
            }
            // 如果獲取到計算結果,那麼將活躍任務(active)數減一,並且返回具體的任務結果。
            if (f != null) {
                --active;
                // 如果獲取計算結果有異常,那麼記錄異常信息,繼續循環獲取其他任務的計算結果
                try {
                    return f.get();
                } catch (ExecutionException eex) {
                    ee = eex;
                } catch (RuntimeException rex) {
                    ee = new ExecutionException(rex);
                }
            }
        }
        // 到此任務已經全部結束,但是沒有任何一個任務正常結束。如果記錄的異常不爲空則拋出記錄的異常信息,否則創建一個執行任務異常並拋出。
        if (ee == null)
            ee = new ExecutionException();
        throw ee;

    } finally {
        // 取消所有任務。到這或者是有一個任務已經結束(結束任務依然可以取消,只是沒有效果)需要將其他任務取消,或者所有任務都非正常結束(取消任務沒有效果)。
        for (int i = 0, size = futures.size(); i < size; i++)
            futures.get(i).cancel(true);
    }
}

public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
    throws InterruptedException, ExecutionException {
    try {
        return doInvokeAny(tasks, false, 0);
    } catch (TimeoutException cannotHappen) {
        assert false;
        return null;
    }
}

public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                       long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException {
    return doInvokeAny(tasks, true, unit.toNanos(timeout));
}

public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    throws InterruptedException {
    if (tasks == null)
        throw new NullPointerException();
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
    // 任務是否全部結束標誌
    boolean done = false;
    try {
        // 構建 RunnableFuture
        // 將計算結果存結果集中
        // 執行任務
        for (Callable<T> t : tasks) {
            RunnableFuture<T> f = newTaskFor(t);
            futures.add(f);
            execute(f);
        }
        // 循環遍歷計算結果,如果有未完成,那麼阻塞等待任務計算完成
        for (int i = 0, size = futures.size(); i < size; i++) {
            Future<T> f = futures.get(i);
            if (!f.isDone()) {
                try {
                    f.get();
                } catch (CancellationException ignore) {
                } catch (ExecutionException ignore) {
                }
            }
        }
        done = true;
        return futures;
    } finally {
        // done == false 表示在執行任務時(execute(f))或者之前已經出現異常情況,比如當前線程被中斷導致無法全部提交,那麼將任務全部取消釋放資源。
        if (!done)
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
    }
}

public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                     long timeout, TimeUnit unit)
    throws InterruptedException {
    if (tasks == null)
        throw new NullPointerException();
    long nanos = unit.toNanos(timeout);
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
    boolean done = false;
    try {
        // 構建計算結果並加到結果集中
        for (Callable<T> t : tasks)
            futures.add(newTaskFor(t));

        // 超時時間節點
        final long deadline = System.nanoTime() + nanos;
        final int size = futures.size();

        // 循環遍歷結果集並執行任務。每次執行後立即檢查超時時間。如果超時則直接返回結果集。既然已經超時,後續任務已經沒必要開始。
        for (int i = 0; i < size; i++) {
            execute((Runnable)futures.get(i));
            nanos = deadline - System.nanoTime();
            if (nanos <= 0L)
                return futures;
        }

        // 循環遍歷結果集,如果沒有完成則阻塞等待完成。
        for (int i = 0; i < size; i++) {
            Future<T> f = futures.get(i);
            if (!f.isDone()) {
                if (nanos <= 0L)
                    return futures;
                try {
                    f.get(nanos, TimeUnit.NANOSECONDS);
                } catch (CancellationException ignore) {
                } catch (ExecutionException ignore) {
                } catch (TimeoutException toe) {
                    return futures;
                }
                nanos = deadline - System.nanoTime();
            }
        }
        done = true;
        return futures;
    } finally {
        if (!done)
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章