completionService

我们现在在Java中使用多线程通常不会直接用Thread对象了,而是会用到java.util.concurrent包下的ExecutorService类来初始化一个线程池供我们使用。

当我们使用ExecutorService来做多线程处理时,习惯自己维护一个list保存submit的callable task所返回的Future对象。

然后在主线程中遍历这个list并调用Future的get()方法取到Task的返回值。

这两者最主要的区别在于submit的task不一定是按照加入自己维护的list顺序完成的。

从list中遍历的每个Future对象并不一定处于完成状态,这时调用get()方法就会被阻塞住,如果系统是设计成每个线程完成后就能根据其结果继续做后面的事,这样对于处于list后面的但是先完成的线程就会增加了额外的等待时间。

比如:浏览器在渲染某个页面时,需要下载很多图片,我们把下载图片放到ExecutorService的tast里面处理,这样我们只能按照放入list的图片顺序来渲染图片,如果有些图片比较大,又比较早的被放入的提交的list<task>,这时候就比较影响用户体验了。

如果我们改用completionService,那就可以通过调用completionService.take(),达到只有有图片下载成功,我们就可以优先渲染(展示)这张图片的目的(我想浏览器应该也是按照逻辑来设计的吧)。

我们来看下CompletionService的一个具体实现的一个具体实现ExecutorCompletionService,

1、private final BlockingQueue<Future<V>> completionQueue; //维护一个阻塞队列

2、protected void done() { completionQueue.add(task); }//当某个task完成的时候,就把该task放入队列中

3、public Future<V> take() throws InterruptedException {

return completionQueue.take();
} //从阻塞队列中拿到已经完成的task

这样整个功能就很清晰了。

时间: 2024-10-15 15:58:50

completionService的相关文章

Java线程之CompletionService批处理任务

如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果,怎么办呢? 为此你可以保存与每个任务相关联的Future,然后不断地调用 timeout为零的get,来检验Future是否完成.这样做固然可以,但却相当乏味.幸运的是,还有一个更好的方法:完成服务 (Completion service). CompletionService整合了Executor和BlockingQueue的功能. 你可以将Callable任务提交给它去执行,然 后使用类似于队列中的take和poll

Java线程之CompletionService

CompletionService的使用 当我们使用ExecutorService创建一个线程池时, 如果执行了多个Callable任务后, 每个Callable任务都会产生一个Future, 如果我们需要处理这些任务产生的结果, 那么就需要将这些Future放入一个线性表中, 用于之后的数据处理. 有了CompletionService, 我们就不用人为地去创建线性表来存这些Future了, CompleService是一个更高级的EexcutorService, 它自身自带一个线程安全的线性

使用CompletionService结合ExecutorService批处理任务

CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象. 如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果.为此你可以将每个任务的Future保存进一个集合,然后循环这个集合调用Future的get()取出数据.幸运的是CompletionService帮你做了这件事情. CompletionService整合了Executor和BlockingQueue的功能.你可以将Callabl

11、java5线程池之异步任务CompletionService

JDK文档描述: public interface CompletionService<V> 将生产新的异步任务与使用已完成任务的结果分离开来的服务.生产者 submit 执行的任务.使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果.例如,CompletionService 可以用来管理异步 IO ,执行读操作的任务作为程序或系统的一部分提交,然后,当完成读操作时,会在程序的不同部分执行其他操作,执行操作的顺序可能与所请求的顺序不同. 通常,CompletionServi

JDK并发工具包CompletionService和ExecutorCompletionService的好处和使用场景

<Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Executor提交了一组计算任务,并且希望在计算完成后获得结果,那么可以保留与每个任务关联的Future,然后反复使用get方法,同时将参数timeout指定为0,从而通过轮询来判断任务是否完成.这种方法虽然可行,但却有些繁琐.幸运的是,还有一种更好的方法:完成服务CompletionService." 这是什么意思呢?我们通过

计算机程序的思维逻辑 (79) - 方便的CompletionService

上节,我们提到,在异步任务程序中,一种常见的场景是,主线程提交多个异步任务,然后希望有任务完成就处理结果,并且按任务完成顺序逐个处理,对于这种场景,Java并发包提供了一个方便的方法,使用CompletionService,这是一个接口,它的实现类是ExecutorCompletionService,本节我们就来探讨它们. 基本用法 接口和类定义 与77节介绍的ExecutorService一样,CompletionService也可以提交异步任务,它的不同是,它可以按任务完成顺序获取结果,其具

Java并发专题 带返回结果的批量任务运行 CompletionService ExecutorService.invokeAll

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 普通情况下,我们使用Runnable作为主要的任务表示形式,可是Runnable是一种有非常大局限的抽象,run方法中仅仅能记录日志,打印,或者把数据汇总入某个容器(一方面内存消耗大,还有一方面须要控制同步,效率非常大的限制),总之不能返回运行的结果:比方同一时候1000个任务去网络上抓取数据,然后将抓取到的数据进行处理(处理方式不定),我认为最好的方式就是提供回

Java批处理ExecutorService/CompletionService

服务端接收一个请求,常常需要同时进行几个计算或者向其他服务发送请求,最后拼装结果返回上游.本文就来看下JDK提供几个并行处理方案,牵涉到ExcecutorService/CompletionService.要实现的场景是请求有超时限制,如果所有操作都计算完成,则全部拼装返回:否则只拼装部分完成的结果. 1.前提 //任务类,sleep一个时间代表这个计算需要的耗时,返回一个计算结果. public class MyTask implements Callable<Integer> { priv

ExecutorService与CompletionService

我们现在在Java中使用多线程通常不会直接用Thread对象了,而是会用到java.util.concurrent包下的ExecutorService类来初始化一个线程池供我们使用. 之前我一直习惯自己维护一个list保存submit的callable task所返回的Future对象. 在主线程中遍历这个list并调用Future的get()方法取到Task的返回值. 但是,我在很多地方会看到一些代码通过CompletionService包装ExecutorService,然后调用其take(

并发编程—— CompletionService : Executor 和 BlockingQueue

Java并发编程实践 目录 并发编程—— ConcurrentHashMap 并发编程—— 阻塞队列和生产者-消费者模式 并发编程—— 闭锁CountDownLatch 与 栅栏CyclicBarrier 并发编程—— Callable和Future 并发编程—— CompletionService : Executor 和 BlockingQueue 概述 第1部分 问题引入 第2部分 第1部分 问题引入 <Java并发编程实践>一书6.3.5节CompletionService:Execu