• ExecutorCompletionService


    CompletionService和ExecutorCompletionService的实现

    使用executor提交任务,接收类型future.get()获取结果的顺序是线程执行先后的顺序。

    使用ExecutorCompletionService提交任务,CompletionService的take()方法接收future类型的返回值,获取的结果顺序是线程执行完毕的顺序

     JDK源码中CompletionService的javadoc说明如下:

    复制代码
    /**
     * A service that decouples the production of new asynchronous tasks
     * from the consumption of the results of completed tasks.  Producers
     * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
     * completed tasks and process their results in the order they
     * complete. 
     */
    复制代码
    也就是说,CompletionService实现了生产者提交任务和消费者获取结果的解耦,生产者和消费者都不用关心任务的完成顺序,由CompletionService来保证,消费者一定是按照任务完成的先后顺序来获取执行结果。

    ExecutorCompletionService是CompletionService的实现,融合了线程池Executor和阻塞队列BlockingQueue的功能。
    复制代码
     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>>();
        }
    复制代码
    到这里可以推测,按照任务的完成顺序获取结果,就是通过阻塞队列实现的,阻塞队列刚好具有这样的性质:阻塞和有序。
     
    ExecutorCompletionService任务的提交和执行都是委托给Executor来完成。当提交某个任务时,该任务首先将被包装为一个QueueingFuture
    复制代码
    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;
    }
    复制代码

    QueueingFuture是FutureTask的一个子类,通过改写FutureTask类的done方法,可以实现当任务完成时,将结果放入到BlockingQueue中。

    复制代码
    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;
        }
    复制代码

    FutureTask.done(),这个方法默认什么都不做,就是一个回调,当提交的线程池中的任务完成时,会被自动调用。这也就说时候,当任务完成的时候,会自动执行QueueingFuture.done()方法,将返回结果加入到阻塞队列中,加入的顺序就是任务完成的先后顺序。

  • 相关阅读:
    威马汽车Java实习面试(offer到手含面试经验及答案)
    满帮集团Java实习面试(offer到手含面试经验及答案)
    云杉世界Java实习面试(offer到手含面试经验及答案)
    商汤科技Java实习面试(offer到手含面试经验及答案)
    苏宁金融Java实习面试(offer到手含面试经验及答案)
    c++ 命令行执行
    2015 经典的ImageCaptioning论文
    c++ istringstream用法
    python操作excel——新建、写入、读取基本操作
    python包matplotlib绘制图像
  • 原文地址:https://www.cnblogs.com/itfeng813/p/14659345.html
Copyright © 2020-2023  润新知