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

}

猜你喜欢

转载自my.oschina.net/u/3858564/blog/2961906