`
bugyun
  • 浏览: 557049 次
社区版块
存档分类
最新评论

CompletionService 简介(转)

 
阅读更多

 

转自:http://my.oschina.net/jielucky/blog/158839

 

当向Executor提交批处理任务时,并且希望在它们完成后获得结果,如果用FutureTask,你可以循环获取task,并用future.get()去获取结果,但是如果这个task没有完成,你就得阻塞在这里,这个实效性不高,其实在很多场合,其实你拿第一个任务结果时,此时结果并没有生成并阻塞,其实在阻塞在第一个任务时,第二个task的任务已经早就完成了,显然这种情况用future task不合适的,效率也不高。
       自己维护list和CompletionService的区别:

  1. 从list中遍历的每个Future对象并不一定处于完成状态,这时调用get()方法就会被阻塞住,如果系统是设计成每个线程完成后就能根据其结果继续做后面的事,这样对于处于list后面的但是先完成的线程就会增加了额外的等待时间。
  2. 而CompletionService的实现是维护一个保存Future对象的BlockingQueue。只有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。

       CompletionService采取的是BlockingQueue<Future<V>>无界队列来管理Future。则有一个线程执行完毕把返回结果放到BlockingQueue<Future<V>>里面。就可以通过completionServcie.take().get()取出结果。

         方法区别:

  • take 方获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。<如果需要用到返回值建议用take>
  • poll 获取并移除表示下一个已完成任务的 Future,如果不存在这样的任务,则返回null。

以下是jdk关于CompletionService的简介:

  •    public interface CompletionService<V>
  • 将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。例如,CompletionService 可以用来管理异步 IO ,执行读操作的任务作为程序或系统的一部分提交,然后,当完成读操作时,会在程序的不同部分执行其他操作,执行操作的顺序可能与所请求的顺序不同。
  • 通常,CompletionService 依赖于一个单独的 Executor 来实际执行任务,在这种情况下,CompletionService 只管理一个内部完成队列。ExecutorCompletionService 类提供了此方法的一个实现。 
  • 内存一致性效果:线程中向 CompletionService 提交任务之前的操作 happen-before 该任务执行的操作,后者依次 happen-before 紧跟在从对应 take() 成功返回的操作。 

废话少说,直接看代码:

 

package com.lucky.concurrent;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletionServiceDemo {

	public static class Task implements Callable<Integer> {
		private int i;

		Task(int i) {
			this.i = i;
		}

		@Override
		public Integer call() throws Exception {
			Thread.sleep(new Random().nextInt(5000));
			System.out.println(Thread.currentThread().getName() + "   " + i);
			return i;
		}
	}

	public void run() {
		ExecutorService pool = Executors.newFixedThreadPool(10);
		CompletionService<Integer> completionServcie = new ExecutorCompletionService<Integer>(
				pool);
		try {
			for (int i = 0; i < 10; i++) {
				completionServcie.submit(new CompletionServiceDemo.Task(i));
			}
			for (int i = 0; i < 10; i++) {
				// take 方法等待下一个结果并返回 Future 对象。
				// poll 不等待,有结果就返回一个 Future 对象,否则返回 null。
				System.out.println(completionServcie.take().get());
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		} finally {
			pool.shutdown();
		}
	}

	public static void main(String[] args) {
		new CompletionServiceDemo().run();
	}
}

直接结果: 
 

 

从结果中不难看出。只要有一个线程执行完毕后,主程序就立马获取结果。

 

分享到:
评论

相关推荐

    ExecutorService与CompletionService对比详解.docx

    ExecutorService 和 CompletionService 是Java并发处理中的两种工具,它们用于管理和执行多个任务。ExecutorService 是一个接口,它是java.util.concurrent.Executor 接口的扩展,提供了一组方法来管理和控制线程池...

    32 请按到场顺序发言—Completion Service详解.pdf

    `CompletionService`是Java并发编程中的一个重要工具,它在`ExecutorService`的基础上提供了一种更加高效的方式来管理和处理并发任务的完成结果。`ExecutorService`允许我们提交任务(通常是`Runnable`或`Callable`...

    基于java开发的NIO+多线程实现聊天室+源码+项目解析(毕业设计&课程设计&项目开发)

    项目简介: 涉及到的技术点 线程池ThreadPoolExecutor 阻塞队列BlockingQueue,生产者消费者模式 Selector Channel ByteBuffer ProtoStuff 高性能序列化 HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子...

    通过多线程任务处理大批量耗时业务并返回结果

    `CompletionService`是另一个关键工具,它扩展了`ExecutorService`的功能,尤其适用于需要在任务完成时立即获取结果的情况。`CompletionService`通过`Future`接口返回每个任务的结果,使得我们可以在任务完成的瞬间...

    线程实例(并发库引入到Java标准库 )

    有以下类的实例: ThreadPool ScheduledThread CyclicBarrier BlockingQueue CountDownLatch FutureTask CompletionService Semaphore

    浅谈Java多线程处理中Future的妙用(附源码)

    CompletionService是一个可以帮助我们并发处理任务的工具,它可以将Future收集到一个队列里,可以按结果处理完成的先后顺序进队。这样我们可以轻松地实现并发处理大量任务,并且可以方便地获取处理结果。 下面是一...

    java多线程并发编程例子

    3. **CompletionService**:`CompletionService`提供了一种获取异步任务结果的机制,它基于`ExecutorService`,使得你可以按完成顺序获取结果,而不需要知道任务的原始提交顺序。`TestCompletionService.java`可能...

    Java并发编程实战

    第1章 简介 1.1 并发简史 1.2 线程的优势 1.2.1 发挥多处理器的强大能力 1.2.2 建模的简单性 1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性...

    Java 并发编程实战

    第1章 简介 1.1 并发简史 1.2 线程的优势 1.2.1 发挥多处理器的强大能力 1.2.2 建模的简单性 1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性...

    Java利用future及时获取多线程运行结果

    为了解决这个问题,可以使用CompletionService,它内部添加了阻塞队列,从而获取future中的值,然后根据返回值做对应的处理。下面是一个使用Future和CompletionService的示例代码: 首先,定义一个多线程执行任务的...

    java多线程程序设计:Java NIO+多线程实现聊天室

    CompletionService log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣电影的图片,并打为压缩包传输给客户端 客户端使用方式: 登录:默认...

    springboot集成amazon aws s3对象存储sdk(javav2)

    CompletionService&lt;PartETag&gt; completionService = new ExecutorCompletionService(executor); for (int i = 1; i ; i++) { UploadPartResponse response = s3Client.uploadPart(uploadRequestBuilder.part...

    tigase 内部处理流程

    - 通过`completionService.submit(serv)`提交执行`XMPPIOService.call()`,完成从Socket报文到Packet的转换。 2. **Packet处理**: - 接收的Socket报文通过`XMPPIOService.call()`转换为Packet,这是内部处理的...

    java并发(二十四)多线程结果组装

    通过`CompletionService.submit(Callable)`提交任务,然后调用`take()`或`poll()`方法来获取最先完成的任务结果,这样可以按照任务完成的顺序组装结果,无需等待所有任务完成。 另外,`CompletableFuture`是Java 8...

    JAVA课程学习笔记.doc

    - `java.util.concurrent.CompletionService`:允许获取执行任务的结果,`ExecutorCompletionService` 是其具体实现,结合了 `ExecutorService` 和 `Future`。 5. 线程池执行原理 线程池的执行过程主要包括任务提交...

    java多线程异步性

    在Java中,通常通过Future和Callable接口实现异步计算,或者使用ExecutorService和CompletionService来管理和控制异步任务。 三、ExecutorService与ThreadPoolExecutor ExecutorService是Java并发框架中的核心接口...

    个人总结的深入java多线程开发

    9)已完成任务队列CompletionService 36 10)计时器CountDownLatch 37 11)周期性同步工具CyclicBarrier 38 12)异步计算的结果Future 40 13)安排线程池ScheduledExecutorService 40 五多线程面试题 41 六其他主题 41 1)...

    笔记-6、线程池1

    Java的并发编程框架`java.util.concurrent`包提供了`Executor`接口和相关的实现,包括`ExecutorService`、`CompletionService`等,它们使得并发编程更加简洁高效。`CompletionService`允许获取已完成任务的结果,...

Global site tag (gtag.js) - Google Analytics