Java ~ Executor ~ ExecutorCompletionService【源码】

前言


 文章

一 ExecutorCompletionService(执行器完成服务)类源码及机制详解


 类

    任务的“生产”与“消费”默认是同步的。在正式讲述ExecutorCompletionService(执行器完成服务)类的作用之前我们需要先了解所谓任务的“生产”与“消费”是什么概念。在Executor(执行器)框架中任务的“生产”指任务向执行器递交的行为,而“消费”则指将任务从执行器中移除的行为,即执行器不再持有任务的引用,因此“消费”只能在任务执行结束后(完成/异常/取消)后发生。任务的“生产”与“消费”通常被认为是同步的,这是一个会让初学者非常疑惑的点,因为基于大多数执行器接口实现类都采用异步执行方案的原因,并无法保证递交方法会在任务“消费”后返回,因此同步就显得毫无道理。那为什么还会有同步的说法呢?这是因为递交方法同步返回的Future(未来)拥有追踪任务执行状态的能力。因此即使任务被执行器异步执行,也可在需要时通过调用未来的get()方法达到同步“消费”(并获取执行结果/异常)的目的,其效果与任务在递交时即被同步“消费”是等价的,因此任务的“生产”与“消费”本质是一种间接/变相的同步。

    同步“消费”的前提是确定具体需要被“消费”的任务。想要进行同步“消费”就必须先确定具体需要被“消费”的任务,这其中原因是因为我们需要调用该任务关联未来的get()方法。这并没有想象中简单,因为递交返回的未来未必是我们想要的目标未来,即递交的任务未必是我们想“消费”的任务。典型的例子是:如何获取一组递交任务中最早执行结束(完成/异常/取消)任务的结果呢?事实上开发者应该很清楚该问题在使用同步“消费”的情况下是无法/很难解决的,因为无法得知哪个同步未来的代表任务会最早执行结束(完成/异常/取消)。因此在包含上述举例在内的某些场景中我们也希望“消费”可以是异步的,即不通过调用同步未来get()方法的方式来“消费”任务,以达到对任务“消费”的顺序/时间/条件等多项维度进行自定义的目的。

    CompletionService(完成服务)接口在定义上提供将任务的“生产”与“消费”从概念上分离的能力,而执行器完成服务类实现了这种能力,并支持按结束(完成/异常/取消)顺序对任务进行异步“消费”。完成服务接口在递交方法的基础上额外定义了移除方法对递交至完成服务的任务进行“消费”(并返回相关的未来),使得任务的“生产”与“消费”之间失去了交集而由原本的同步关系转变为了异步关系。因此作为完成服务接口的唯一实现类,执行器完成服务类天然具有分离任务“生产”与“消费”的能力。并且为了实现上述获取一组递交任务中最早执行结束(完成/异常/取消)任务结果的需求,执行器完成服务类会按结束(完成/异常/取消)的顺序对任务进行异步“消费”,即先被异步“消费”的任务一定比后被异步“消费”的任务先执行结束(完成/异常/取消)。该功能是通过代理将结束(完成/异常/取消)的任务依次加入阻塞队列中实现的,该功能会在下文详述。任务被异步“消费”后调用异步未来的get()方法,此时的get()方法已不再具有同步“消费”的意义,只单纯的被用来获取任务的执行结果。

/**
 * A {@link CompletionService} that uses a supplied {@link Executor} to execute tasks.  This class arranges that submitted
 * tasks are, upon completion, placed on a queue accessible using {@code take}. The class is lightweight enough to be
 * suitable for transient use when processing groups of tasks.
 * 完成服务使用提供的执行器来执行任务。这个类统筹递交的任务,在完成之后,放置于一个可使用take()方法访问的队列。这个
 * 类是足够轻量级的,合适在执行一组任务时短暂的使用。
 * <p>
 * <b>Usage Examples.</b>
 * 用法实例。
 * Suppose you have a set of solvers for a certain problem, each returning a value of some type {@code Result}, and would
 * like to run them concurrently, processing the results of each of them that return a non-null value, in some method
 * {@code use(Result r)}. You could write this as:
 * 假设你有一组解决者用于一个特定的问题,每个都会返回一个Result类型的值,并且想要在一些use(Result r)方法中并发地运行,
 * 处理每个返回的非空值的结果,你可以像这样写:
 *
 * <pre> {@code
 * void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException, ExecutionException {
 *     // 创建一个CompletionService对象。
 *     CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
 *     // 循环递交任务。
 *     for (Callable<Result> s : solvers)
 *         ecs.submit(s);
 *     // 循环获取任务的执行结果。
 *     int n = solvers.size();
 *     for (int i = 0; i < n; ++i) {
 *         Result r = ecs.take().get();
 *         if (r != null)
 *             use(r);
 *     }
 * }}</pre>
 * <p>
 * Suppose instead that you would like to use the first non-null result of the set of tasks, ignoring any that encounter
 * exceptions, and cancelling all other tasks when the first one is ready:
 * 假设你想要使用一组任务中第一个不为null的结果代替,忽略任意遭遇的异常,并且当第一个任务准备好时取消所有其它任务:
 *
 * <pre> {@code
 * void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
 *     // 创建一个CompletionService实例。
 *     CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
 *     // 声明一个与任务集长度相同的列表用于保存结果。
 *     int n = solvers.size();
 *     List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
 *     Result result = null;
 *     try {
 *         // 循环的递交所有任务,并保存所有代表任务的Future。
 *         for (Callable<Result> s : solvers)
 *             futures.add(ecs.submit(s));
 *         // 遍历Future列表,并获取到第一个不为null的结果,在过程中遇到的所有异常全部忽略。
 *         for (int i = 0; i < n; ++i) {
 *             try {
 *                 Result r = ecs.take().get();
 *                 if (r != null) {
 *                     result = r;
 *                     break;
 *                 }
 *             } catch (ExecutionException ignore) {}
 *         }
 *     } finally {
 *         // 成功获取后,取消所有的任务。
 *         for (Future<Result> f : futures)
 *             f.cancel(true);
 *     }
 *     // 使用具体的结果。
 *     if (result != null)
 *         use(result);
 * }}</pre>
 *
 * @Description: 执行器完成服务
 */
public class ExecutorCompletionService<V> implements CompletionService<V> {
    ...
}

 字段

  • executor —— 执行器 —— 持有当前执行器完成服务
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 执行器
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 持有当前执行器完成服务的执行器
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private final Executor executor;
  • aes —— 抽象执行器服务 —— 持有当前执行器完成服务的抽象执行器服务,其通常与[执行器]是相等的。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 抽象执行器服务
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 持有当前执行器完成服务的抽象执行器服务,其通常与[执行器]是相等的。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private final AbstractExecutorService aes;
  • completionQueue —— 完成队列 —— 持有当前执行器完成服务的完成队列,用于保存已结束(完成/异常/取消)的任务。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 完成队列
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 持有当前执行器完成服务的完成队列,用于保存已结束(完成/异常/取消)的任务。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private final BlockingQueue<Future<V>> completionQueue;

 构造方法

  • public ExecutorCompletionService(Executor executor) —— 执行器完成服务 —— 创建指定执行器,且完成队列默认为链接阻塞队列的执行器完成服务。
        方法首先会判断指定执行器是否为null,是则直接抛出空指针异常;否则存入[执行器]。随后判断指定执行器是否是抽象执行器服务类型,是则转换并存入[抽象执行器服务],用于将可运行/可调用/任务封装为可运行未来/任务使用。最后创建一个链接阻塞队列作为[完成队列]。
    /**
     * Creates an ExecutorCompletionService using the supplied executor for base task execution and a
     * {@link LinkedBlockingQueue} as a completion queue.
     * 使用提供的执行器创建一个执行器完成服务用于基础任务的执行并将链接阻塞队列作为一个完成队列。
     *
     * @param executor the executor to use 要使用的执行器
     * @throws NullPointerException if executor is {@code null}
     *                              空指针异常:如果执行器为null
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 执行器完成服务
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 创建指定执行器,且完成队列默认为链接阻塞队列的执行器完成服务
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断指定执行器是否为null,是则直接抛出空指针异常;否则存入[执行器]。随后判断指定执行
     * @Description: 器是否是抽象执行器服务类型,是则转换并存入[抽象执行器服务],用于将可运行/可调用/任务封装为可
     * @Description: 运行未来/任务使用。最后创建一个链接阻塞队列作为[完成队列]。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    public ExecutorCompletionService(Executor executor) {
        if (executor == null)
            throw new NullPointerException();
        this.executor = executor;
        // 如果执行器是一个AbstractExecutorService的实例(AbstractExecutorService是抽象类,因此不可能是直接的
        // AbstractExecutorService类对象,因此实际上判断的是其子类对象),则设置aes,否则为null。
        this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null;
        // 声明一个LinkedBlockingQueue作为完成队列。
        this.completionQueue = new LinkedBlockingQueue<Future<V>>();
    }
  • public ExecutorCompletionService(Executor executor, BlockingQueue<Future> completionQueue) —— 执行器完成服务 —— 创建指定执行器及完成队列的执行器完成服务。
        方法首先会判断指定执行器及完成队列是否为null,是则直接抛出空指针异常;否则存入[执行器]及[完成队列]。随后判断指定执行器是否是抽象执行器服务类型,是则转换并存入[抽象执行器服务],用于将可运行/可调用/任务封装为可运行未来/任务使用。
    /**
     * Creates an ExecutorCompletionService using the supplied executor for base task execution and the supplied queue as
     * its completion queue.
     * 使用提供的执行器创建一个ExecutorCompletionService用于基础任务执行并将提供的队列作为完成队列。
     *
     * @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.
     *                        该队列通常被这个服务专用于作为完成队列使用。这个队列被看做是无边界的(实际上还是有的,因为
     *                        长度受限于int类型的最大值) —— 已完成的任务尝试Queue.add()操作失败造成它们无法被检索。
     * @throws NullPointerException if executor or completionQueue are {@code null} 如果执行器或完成队列为null
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 执行器完成服务
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 创建指定执行器及完成队列的执行器完成服务
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断指定执行器及完成队列是否为null,是则直接抛出空指针异常;否则存入[执行器]及[完成队
     * @Description: 列]。随后判断指定执行器是否是抽象执行器服务类型,是则转换并存入[抽象执行器服务],用于将可运行/
     * @Description: 可调用/任务封装为可运行未来/任务使用。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    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;
    }

 方法

  • private RunnableFuture newTaskFor(Callable task) —— 新任务 —— 将指定可调用/任务封装为可运行未来/任务。
        方法首先会判断[抽象执行器服务]是否存在,如果不存在则直接将指定可调用/任务作为构造参数创建未来任务;否则使用[抽象执行器服务]的newTaskFor(Callable task)方法创建可运行未来/任务。由此可知如果持有的[执行器]是抽象执行器服务的话,执行器完成服务类推荐使用[执行器]来封装可调用/任务。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 新任务
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 将指定可调用/任务封装为可运行未来/任务
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断[抽象执行器服务]是否存在,如果不存在则直接将指定可调用/任务作为构造参数创建未来
     * @Description: 任务;否则使用[抽象执行器服务]的newTaskFor(Callable<V> task)方法创建可运行未来/任务。由此可知如
     * @Description: 果持有的[执行器]是抽象执行器服务的话,执行器完成服务类推荐使用[执行器]来封装可调用/任务。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private RunnableFuture<V> newTaskFor(Callable<V> task) {
        if (aes == null)
            return new FutureTask<V>(task);
        else
            // 使用组合的AbstractExecutorService对象来创建一个RunnableFuture对象。
            return aes.newTaskFor(task);
    }
  • private RunnableFuture newTaskFor(Runnable task, V result) —— 新任务 —— 将指定可运行/任务封装为可运行未来/任务,方法会同步传入用于承载任务执行结果的变量。
        方法首先会判断[抽象执行器服务]是否存在,如果不存在则直接将指定可运行/任务作为构造参数创建未来任务;否则使用[抽象执行器服务]的newTaskFor(Runnable task, V result)方法创建可运行未来/任务。由此可知如果持有的[执行器]是抽象执行器服务的话,执行器完成服务类推荐使用[执行器]来封装可运行/任务。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 新任务
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 将指定可运行/任务封装为可运行未来/任务,方法会同步传入用于承载任务执行结果的变量。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断[抽象执行器服务]是否存在,如果不存在则直接将指定可运行/任务作为构造参数创建未来
     * @Description: 任务;否则使用[抽象执行器服务]的newTaskFor(Runnable task, V result)方法创建可运行未来/任务。由此
     * @Description: 可知如果持有的[执行器]是抽象执行器服务的话,执行器完成服务类推荐使用[执行器]来封装可运行/任务。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private RunnableFuture<V> newTaskFor(Runnable task, V result) {
        if (aes == null)
            return new FutureTask<V>(task, result);
        else
            // 使用组合的AbstractExecutorService对象来创建一个RunnableFuture对象。
            return aes.newTaskFor(task, result);
    }
  • public Future submit(Callable task) —— 递交 —— 向当前完成服务递交指定可回调/任务,并返回可追踪/获取指定可回调/任务执行状态/结果/异常的未来,但不推荐直接使用该未来。
        方法首先会判断指定可回调/任务是否为null,是则直接抛出空指针异常;否则调用newTaskFor(Callable < V > task)方法将可回调/任务封装为可运行未来,随后再将可运行未来作为构造参数封装为排队未来并调用[执行器]的execute(Runnable command)方法执行该未来。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 递交
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 向当前完成服务递交指定可回调/任务,并返回可追踪/获取指定可回调/任务执行状态/结果/异常的未来,
     * @Description: 但不推荐直接使用该未来。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断指定可回调/任务是否为null,是则直接抛出空指针异常;否则调用
     * @Description: newTaskFor(Callable < V > task)方法将可回调/任务封装为可运行未来,随后再将可运行未来作为构造参数
     * @Description: 封装为排队未来并调用[执行器]的execute(Runnable command)方法执行该未来。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    @Override
    public Future<V> submit(Callable<V> task) {
        if (task == null) throw new NullPointerException();
        // 为Callable接口任务创建一个RunnableFuture接口对象(一般是FutureTask类对象)。
        RunnableFuture<V> f = newTaskFor(task);
        //     以创建的RunnableFuture接口对象为基础再创建一个QueueingFuture类对象,这是一个新的RunnableFuture接口对象,
        // 将以Callable接口任务创建一个RunnableFuture接口对象作为任务执行。
        executor.execute(new QueueingFuture(f));
        return f;
    }
  • public Future submit(Runnable task, V result) —— 递交 —— 向当前完成服务递交指定可运行/任务,并返回可追踪/获取指定可运行/任务执行状态/结果/异常的未来,但不推荐直接使用该未来。方法会同步传入用于承载执行结果的变量。
        方法首先会判断指定可运行/任务是否为null,是则直接抛出空指针异常;否则调用newTaskFor(Runnable task, V result)方法将可运行/任务封装为可运行未来,随后再将可运行未来作为构造参数封装为排队未来并调用[执行器]的execute(Runnable command)方法执行该未来。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 递交
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 向当前完成服务递交指定可运行/任务,并返回可追踪/获取指定可运行/任务执行状态/结果/异常的未来,
     * @Description: 但不推荐直接使用该未来。方法会同步传入用于承载执行结果的变量。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法首先会判断指定可运行/任务是否为null,是则直接抛出空指针异常;否则调用
     * @Description: newTaskFor(Runnable task, V result)方法将可运行/任务封装为可运行未来,随后再将可运行未来作为构
     * @Description: 造参数封装为排队未来并调用[执行器]的execute(Runnable command)方法执行该未来。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    @Override
    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 take() throws InterruptedException —— 拿取 —— 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/异常/取消)未来时返回,否则无限等待至存在为止。
        方法直接通过调用[完成队列]的take()方法实现。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 拿取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/
     * @Description: 异常/取消)未来时返回,否则无限等待至存在为止。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法直接通过调用[完成队列]的take()方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    @Override
    public Future<V> take() throws InterruptedException {
        // 从完成队列中获取已经完成的任务。该方法是一个阻塞方法,会一直阻塞到有任务完成。
        return completionQueue.take();
    }
  • public Future poll() —— 轮询 —— 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/异常/取消)未来时返回,否则返回null。
        方法直接通过调用[完成队列]的poll()方法实现。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 拿取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/
     * @Description: 异常/取消)未来时返回,否则无限等待至存在为止。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法直接通过调用[完成队列]的take()方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    @Override
    public Future<V> take() throws InterruptedException {
        // 从完成队列中获取已经完成的任务。该方法是一个阻塞方法,会一直阻塞到有任务完成。
        return completionQueue.take();
    }
  • public Future poll(long timeout, TimeUnit unit) throws InterruptedException —— 轮询 —— 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/异常/取消)未来时返回,否则在指定等待时间内有限等待至存在为止,超时指定等待时间则返回null。
        方法直接通过调用[完成队列]的poll(long timeout, TimeUnit unit)方法实现。
    /**
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 轮询
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 从当前执行器完成服务中获取已结束(完成/异常/取消)未来,当当前执行器完成服务存在已结束(完成/
     * @Description: 异常/取消)未来时返回,否则在指定等待时间内有限等待至存在为止,超时指定等待时间则返回null。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: 方法直接通过调用[完成队列]的poll(long timeout, TimeUnit unit)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    @Override
    public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException {
        return completionQueue.poll(timeout, unit);
    }

二 QueueingFuture(排队未来)类源码及机制详解


 类

    排队未来类是执行器完成服务的私有内部类,同是也是未来任务类的子类。其重写了未来任务来的done()方法,会在代理任务执行结束(完成/异常/取消)时将之加入自身的完成队列中。

    /**
     * FutureTask extension to enqueue upon completion
     * 未来任务衍生在完成后入队
     *
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 队列未来类
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 持有当前执行器完成服务
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private class QueueingFuture extends FutureTask<Void> {
        ...
    }

 字段

  • private final Future task —— 任务 —— 持有当前队列未来中未来的引用。
        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * @Description: 任务
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * @Description: 持有当前队列未来中未来的引用。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * @Description: ~
         */
        private final Future<V> task;

 构造方法

  • QueueingFuture(RunnableFuture task) —— 队列未来 —— 通过指定可运行未来/任务创建队列未来。
        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * @Description: 队列未来
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * @Description: 通过指定可运行未来/任务创建队列未来。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * @Description: ~
         */
        QueueingFuture(RunnableFuture<V> task) {
            super(task, null);
            this.task = task;
        }
  • protected void done() —— 结束 —— 将已结束(完成/异常/取消)任务加入完成队列。
        方法直接将[任务]任务加入[完成队列]中。该方法会在任务结束是被调用。
        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * @Description: 结束
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * @Description: 将已结束(完成/异常/取消)任务加入完成队列。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * @Description: 方法直接将[任务]任务加入[完成队列]中。该方法会在任务结束是被调用。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * @Description: ~
         */
        @Override
        protected void done() {
            completionQueue.add(task);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说淑人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值