java.util.concurrent.AbstractExecutorService 抽象類 源碼 原

線程池相關

源碼:

package java.util.concurrent;

import java.util.*;

public abstract class AbstractExecutorService implements ExecutorService {
    /**
     * 爲給定可運行任務和默認值返回一個RunnableFuture
     * 參數:
     * runnable - 將被包裝的可運行任務
     * value - 用於所返回的將來任務的默認值
     * 返回:
     * 一個 RunnableFuture,在運行的時候,它將運行底層可運行任務,作爲Future任務,它將生成給定值作爲其結果,併爲底層任務提供取消操作。
     */
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    /**
     * 爲給定可調用任務返回一個RunnableFuture。
     * 參數:
     * callable - 將包裝的可調用任務
     * 返回:
     * 一個RunnableFuture,在運行的時候,它將調用底層可調用任務,作爲Future任務,它將生成可調用的結果作爲其結果,併爲底層任務提供取消操作。
     */
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }


    /**
     * 提交一個Runnable任務用於執行,並返回一個表示該任務的Future。
     * 該Future的get方法在成功完成時將會返回null
     *
     * 方法指定者:接口 ExecutorService 中的 submit
     * 參數:task - 要提交的任務
     * 返回:表示任務等待完成的 Future
     */
    public Future<?> submit(Runnable task) {
        if (task == null)//校驗參數
           throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);//創建一個RunnableFuture對象
        execute(ftask);//調用繼承至ExecutorService接口的execute方法
        return ftask;//返回等待任務完成的Future
    }

    /**
     * 提交一個Runnable任務用於執行,並返回一個表示該任務的Future。
     * 該Future的get方法在成功完成時將會返回給定的結果。
     *
     * 方法指定者:接口 ExecutorService 中的 submit
     * 參數:task - 要提交的任務
     * 返回:表示任務等待完成的 Future
     */
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null)//校驗參數
           throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);//創建一個RunnableFuture對象
        execute(ftask);//調用繼承至ExecutorService接口的execute方法
        return ftask;//返回等待任務完成的Future
    }

    /**
     * 提交一個返回值的任務用於執行,返回一個表示任務的未決結果的Future。
     * 該Future的get方法在成功完成時將會返回該任務的結果。
     *
     * 方法指定者:接口 ExecutorService 中的 submit
     * 參數:task - 要提交的任務
     * 返回:表示任務等待完成的 Future
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null)//校驗參數
           throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);//創建一個RunnableFuture對象
        execute(ftask);//調用繼承至ExecutorService接口的execute方法
        return ftask;//返回等待任務完成的Future
    }


    /**
     * invokeAny的主要機制
     */
    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();
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                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);
        }
    }
    
    /**
     * 執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。
     * 一旦正常或異常返回後,則取消尚未完成的任務。
     * 如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
     *
     * 方法指定者:接口ExecutorService中的invokeAny
     * 參數:tasks - 任務 collection
     * 返回:某個任務返回的結果
     * 拋出:
     * InterruptedException - 如果等待時發生中斷
     * ExecutionException - 如果沒有任務成功完成
     */
    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;
        }
    }

    /**
     * 執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。
     * 一旦正常或異常返回後,則取消尚未完成的任務。
     * 如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
     *
     * 方法指定者:接口ExecutorService中的invokeAny
     * 參數:
     * tasks - 任務 collection
     * timeout - 最長等待時間
     * unit - timeout 參數的時間單位
     * 返回:某個任務返回的結果
     * 拋出:
     * InterruptedException - 如果等待時發生中斷
     * ExecutionException - 如果沒有任務成功完成
     * TimeoutException - 如果在所有任務成功完成之前給定的超時期滿
     */
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));//執行上述的私有方法
    }

    /**
     * 執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的Future列表。
     * 返回列表的所有元素的 Future.isDone()爲true。注意,可以正常地或通過拋出異常來終止已完成任務。
     * 如果正在進行此操作時修改了給定的collection,則此方法的結果是不確定的。
     *
     * 方法指定者:接口ExecutorService中的invokeAll
     * 參數:
     * tasks - 任務 collection
     * 返回:
     * 表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同,每個任務都已完成。
     * 拋出:
     * InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務。
     */
    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 {
            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 {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

    /**
     * 執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的Future列表。
     * 返回列表的所有元素的Future.isDone()爲 true。一旦返回後,即取消尚未完成的任務。
     * 注意,可以正常地或通過拋出異常來終止 已完成 任務。如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
     * 指定者:接口ExecutorService中的invokeAll
     * 參數:
     * tasks - 任務 collection
     * timeout - 最長等待時間
     * unit - timeout 參數的時間單位
     * 返回:
     * 表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同。
     * 如果操作未超時,則已完成所有任務。
     * 如果確實超時了,則某些任務尚未完成。
     * 拋出:
     * InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務
     */
    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);
        }
    }
}

 

類 AbstractExecutorService

已實現的接口:

    ExecutorExecutorService

已知子類:

    ThreadPoolExecutor

    此類使用 newTaskFor 返回的 RunnableFuture 實現 submit、invokeAny 和 invokeAll 方法,默認情況下,RunnableFuture 是此包中提供的 FutureTask 類。例如,submit(Runnable) 的實現創建了一個關聯 RunnableFuture 類,該類將被執行並返回。子類可以重寫 newTaskFor 方法,以返回 FutureTask 之外的 RunnableFuture 實現。

    擴展示例。以下是一個類的簡要介紹,該類定製 ThreadPoolExecutor 使用 CustomTask 類替代默認 FutureTask:

 public class CustomThreadPoolExecutor extends ThreadPoolExecutor {

   static class CustomTask<V> implements RunnableFuture<V> {...}

   protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
       return new CustomTask<V>(c);
   }
   protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
       return new CustomTask<V>(r, v);
   }
   // ... add constructors, etc.
 }
 

 

 方法摘要

<T> List<Future<T>>
invokeAll(Collection<? extends Callable<T>> tasks) 
          執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。
<T> List<Future<T>>
invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 
          執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。
<T> T
invokeAny(Collection<? extends Callable<T>> tasks) 
          執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。
<T> T
invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 
          執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。
protected
<T> RunnableFuture<T>
newTaskFor(Callable<T> callable) 
          爲給定可調用任務返回一個 RunnableFuture。
protected
<T> RunnableFuture<T>
newTaskFor(Runnable runnable, T value) 
          爲給定可運行任務和默認值返回一個 RunnableFuture。
<T> Future<T>
submit(Callable<T> task) 
          提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。
 Future<?> submit(Runnable task) 
          提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。
<T> Future<T>
submit(Runnable task, T result) 
          提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。

 從類 java.lang.Object 繼承的方法

 cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

 從接口 java.util.concurrent.ExecutorService 繼承的方法

 awaitTerminationisShutdownisTerminatedshutdownshutdownNow

 從接口 java.util.concurrent.Executor 繼承的方法

 execute

 

newTaskFor

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable,T value)

    爲給定可運行任務和默認值返回一個 RunnableFuture。

    參數:

    runnable - 將被包裝的可運行任務

    value - 用於所返回的將來任務的默認值

    返回:

        一個 RunnableFuture,在運行的時候,它將運行底層可運行任務,作爲 Future 任務,它將生成給定值作爲其結果,併爲底層任務提供取消操作。

 

newTaskFor

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable)

    爲給定可調用任務返回一個 RunnableFuture。

    參數:

    callable - 將包裝的可調用任務

    返回:

        一個 RunnableFuture,在運行的時候,它將調用底層可調用任務,作爲 Future 任務,它將生成可調用的結果作爲其結果,併爲底層任務提供取消操作。

 

submit

public Future<?> submit(Runnable task)

    從接口 ExecutorService 複製的描述

        提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。該 Future 的 get 方法在 成功 完成時將會返回 null。

    指定者:

        接口 ExecutorService 中的 submit

    參數:

    task - 要提交的任務

    返回:

        表示任務等待完成的 Future

 

submit

public <T> Future<T> submit(Runnable task,
                            T result)

    從接口 ExecutorService 複製的描述

        提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。該 Future 的 get 方法在成功完成時將會返回給定的結果。

    指定者:

        接口 ExecutorService 中的 submit

    參數:

    task - 要提交的任務

    result - 返回的結果

    返回:

        表示任務等待完成的 Future

 

submit

public <T> Future<T> submit(Callable<T> task)

    從接口 ExecutorService 複製的描述

        提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。該 Future 的 get 方法在成功完成時將會返回該任務的結果。

        如果想立即阻塞任務的等待,則可以使用 result = exec.submit(aCallable).get(); 形式的構造。

        注:Executors 類包括了一組方法,可以轉換某些其他常見的類似於閉包的對象,例如,將 PrivilegedAction 轉換爲 Callable 形式,這樣就可以提交它們了。

    指定者:

        接口 ExecutorService 中的 submit

    參數:

    task - 要提交的任務

    返回:

        表示任務等待完成的 Future

 

invokeAny

public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException,
                   ExecutionException

    從接口 ExecutorService 複製的描述

        執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。一旦正常或異常返回後,則取消尚未完成的任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。

    指定者:

        接口 ExecutorService 中的 invokeAny

    參數:

    tasks - 任務 collection

    返回:

        某個任務返回的結果

    拋出:

    InterruptedException - 如果等待時發生中斷

    ExecutionException - 如果沒有任務成功完成

 

invokeAny

public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                       long timeout,
                       TimeUnit unit)
            throws InterruptedException,
                   ExecutionException,
                   TimeoutException

    從接口 ExecutorService 複製的描述

        執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。一旦正常或異常返回後,則取消尚未完成的任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。

    指定者:

        接口 ExecutorService 中的 invokeAny

    參數:

    tasks - 任務 collection

    timeout - 最長等待時間

    unit - timeout 參數的時間單位

    返回:

        某個任務返回的結果

    拋出:

    InterruptedException - 如果等待時發生中斷

    ExecutionException - 如果沒有任務成功完成

    TimeoutException - 如果在所有任務成功完成之前給定的超時期滿

 

invokeAll

public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
                          throws InterruptedException

    從接口 ExecutorService 複製的描述

        執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone() 爲 true。注意,可以正常地或通過拋出異常來終止 已完成 任務。如果正在進行此操作時修改了給定的 collection,則此方法的結果是不確定的。

    指定者:

        接口 ExecutorService 中的 invokeAll

    參數:

    tasks - 任務 collection

    返回:

        表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同,每個任務都已完成。

    拋出:

    InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務。

 

invokeAll

public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                     long timeout,
                                     TimeUnit unit)
                          throws InterruptedException

    從接口 ExecutorService 複製的描述

    執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone() 爲 true。一旦返回後,即取消尚未完成的任務。注意,可以正常地或通過拋出異常來終止 已完成 任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。

    指定者:

        接口 ExecutorService 中的 invokeAll

    參數:

    tasks - 任務 collection

    timeout - 最長等待時間

    unit - timeout 參數的時間單位

    返回:

        表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同。如果操作未超時,則已完成所有任務。如果確實超時了,則某些任務尚未完成。

    拋出:

    InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務

 

實現原理

    AbstractExecutorService對ExecutorService的執行任務類型的方法提供了一個默認實現。這些方法包括submit,invokeAny和InvokeAll。

    注意的是來自Executor接口的execute方法是未被實現,execute方法是整個體系的核心,所有的任務都是在這個方法裏被真正執行的,因此該方法的不同實現會帶來不同的執行策略。

    這個在分析ThreadPoolExecutorScheduledThreadPoolExecutor就能看出來。

    首先來看submit方法,它的基本邏輯是這樣的:

        1. 生成一個任務類型和Future接口的包裝接口RunnableFuture的對象

        2. 執行任務

        3. 返回future。

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

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

    因爲submit支持Callable和Runnable兩種類型的任務,因此newTaskFor方法有兩個重載方法:

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    Callable和Runnable的區別在於前者帶返回值,也就是說Callable=Runnable+返回值。

    因此java中提供了一種adapter,把Runnable+返回值轉換成Callable類型。這點可以在newTaskFor中的FutureTask類型的構造函數的代碼中看到:

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }

    public FutureTask(Runnable runnable, V result) {
        sync = new Sync(Executors.callable(runnable, result));
    }

    以下是Executors.callable方法的代碼:

    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

    那麼RunnableAdapter的代碼就很好理解了,它是一個Callable的實現,call方法的實現就是執行Runnable的run方法,然後返回那個value。

    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

    接下來先說說較爲簡單的invokeAll:

        1. 爲每個task調用newTaskFor方法生成得到一個既是Task也是Future的包裝類對象的List

        2. 循環調用execute執行每個任務

        3. 再次循環調用每個Future的get方法等待每個task執行完成

        4. 最後返回Future的list。

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        if (tasks == null || unit == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            // 爲每個task生成包裝對象
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));

            long lastTime = System.nanoTime();

            // 循環調用execute執行每個方法
            // 這裏因爲設置了超時時間,所以每次執行完成後
            // 檢查是否超時,超時了就直接返回future集合
            Iterator<Future<T>> it = futures.iterator();
            while (it.hasNext()) {
                execute((Runnable)(it.next()));
                long now = System.nanoTime();
                nanos -= now - lastTime;
                lastTime = now;
                if (nanos <= 0)
                    return futures;
            }

            // 等待每個任務執行完成
            for (Future<T> f : futures) {
                if (!f.isDone()) {
                    if (nanos <= 0)
                        return futures;
                    try {
                        f.get(nanos, TimeUnit.NANOSECONDS);
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                    long now = System.nanoTime();
                    nanos -= now - lastTime;
                    lastTime = now;
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (Future<T> f : futures)
                    f.cancel(true);
        }
    }

    最後說說invokeAny,它的難點在於只要一個任務執行成功就要返回,並且會取消其他任務,也就是說重點在於找到第一個執行成功的任務。

    因爲兩個invokeAny方法都是調用doInvokeAny方法,下面是doInvokeAny的代碼分析:

    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();
        List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
        // ExecutorCompletionService負責執行任務,後面調用用poll返回第一個執行結果
        ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this);

        // 這裏出於效率的考慮,每次提交一個任務之後,就檢查一下有沒有執行完成的任務
        try {
            ExecutionException ee = null;
            long lastTime = timed ? System.nanoTime() : 0;
            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();
                        // 這裏的更新不可少,因爲這個Future可能是執行失敗的情況,那麼還需要再次等待下一個結果,超時的設置還是需要用到。
                        long now = System.nanoTime();
                        nanos -= now - lastTime;
                        lastTime = now;
                    }
                    // 沒有設置超時,並且所有任務都被提交了,則一直等到第一個執行結果出來
                    else
                        f = ecs.take();
                }
                // 有返回結果了,嘗試從future中獲取結果,如果失敗了,那麼需要接着等待下一個執行結果
                if (f != null) {
                    --active;
                    try {
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            // ExecutorCompletionService執行時發生錯誤返回了全是null的future
            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
            // 嘗試取消所有的任務(對於已經完成的任務沒有影響)
            for (Future<T> f : futures)
                f.cancel(true);
        }
    }

    當所有的任務被提交後,任務執行返回的Future會被依次添加到一個BlockingQueue中,然後找到第一個執行成功任務的方法就是從BlockingQueue取出第一個元素,這個就是doInvokeAny方法用到的ExecutorCompletionService的基本原理。 

package java.util.concurrent;

public class ExecutorCompletionService<V> implements CompletionService<V> {
    private final Executor executor;
    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;
        }
        protected void done() { completionQueue.add(task); }
        private final Future<V> task;
    }

    //爲Callable對象實例返回一個RunnableFuture
    private RunnableFuture<V> newTaskFor(Callable<V> task) {
        if (aes == null)
            return new FutureTask<V>(task);
        else
            return aes.newTaskFor(task);
    }

    //爲Runnable對象實例返回一個RunnableFuture
    private RunnableFuture<V> newTaskFor(Runnable task, V result) {
        if (aes == null)
            return new FutureTask<V>(task, result);
        else
            return aes.newTaskFor(task, result);
    }

    //構造器
    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>>();
    }

    //構造器
    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);//創建一個RunnableFuture對象實例
        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);//創建一個RunnableFuture對象實例
        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);
    }

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章