使用CompletionService批处理任务
来源:互联网 发布:海量数据与数据港谁好 编辑:程序博客网 时间:2024/05/22 12:22
分享一篇关于Java中ExecutorService和CompletionService区别,有需要的朋友可以参考一下。
我们现在在Java中使用多线程通常不会直接用Thread对象了,而是会用到java.util.concurrent包下的ExecutorService类来初始化一个线程池供我们使用。
之前我一直习惯自己维护一个list保存submit的callable task所返回的Future对象。
在主线程中遍历这个list并调用Future的get()方法取到Task的返回值。
但是,我在很多地方会看到一些代码通过CompletionService包装ExecutorService,然后调用其take()方法去取Future对象。以前没研究过这两者之间的区别。
今天看了源代码之后就明白了。
这两者最主要的区别在于submit的task不一定是按照加入自己维护的list顺序完成的。
从list中遍历的每个Future对象并不一定处于完成状态,这时调用get()方法就会被阻塞住,如果系统是设计成每个线程完成后就能根据其结果继续做后面的事,这样对于处于list后面的但是先完成的线程就会增加了额外的等待时间。
而CompletionService的实现是维护一个保存Future对象的BlockingQueue。只有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。
所以,先完成的必定先被取出。这样就减少了不必要的等待时间。
import java.util.Random; import java.util.concurrent.BlockingQueue; 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; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; public class Test17 { public static void main(String[] args) throws Exception { Test17 t = new Test17(); t.count1(); t.count2(); } //使用阻塞容器保存每次Executor处理的结果,在后面进行统一处理 public void count1() throws Exception{ ExecutorService exec = Executors.newCachedThreadPool(); BlockingQueue<Future<Integer>> queue = new LinkedBlockingQueue<Future<Integer>>(); for(int i=0; i<10; i++){ Future<Integer> future =exec.submit(getTask()); queue.add(future); } int sum = 0; int queueSize = queue.size(); for(int i=0; i<queueSize; i++){ sum += queue.take().get(); } System.out.println("总数为:"+sum); exec.shutdown(); } //使用CompletionService(完成服务)保持Executor处理的结果 public void count2() throws InterruptedException, ExecutionException{ ExecutorService exec = Executors.newCachedThreadPool(); CompletionService<Integer> execcomp = new ExecutorCompletionService<Integer>(exec); // 线程池外面封装一层CompletionService for(int i=0; i<10; i++){ execcomp.submit(getTask()); } int sum = 0; for(int i=0; i<10; i++){ //检索并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。 Future<Integer> future = execcomp.take(); sum += future.get(); } System.out.println("总数为:"+sum); exec.shutdown(); } //得到一个任务 public Callable<Integer> getTask(){ final Random rand = new Random(); Callable<Integer> task = new Callable<Integer>(){ @Override public Integer call() throws Exception { int i = rand.nextInt(10); int j = rand.nextInt(10); int sum = i*j; System.out.print(sum+"\t"); return sum; } }; return task; } /** * 执行结果: 6 6 14 40 40 0 4 7 0 0 总数为:106 12 6 12 54 81 18 14 35 45 35 总数为:312 */ }
0 0
- 使用CompletionService批处理任务
- 使用CompletionService批处理任务
- 使用CompletionService批处理任务
- 使用CompletionService结合ExecutorService批处理任务
- 使用CompletionService批处理任务(java并发编程第6章)
- CompletionService使用
- Callable和CompletionService的使用,多任务返回值。
- 【Java并发】- 使用CompletionService异步收集任务结果
- 多线程之CompletionService使用
- completionService的使用
- 【Java】CompletionService 使用
- 使用Quartz Scheduler 开发批处理任务
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- 常用网络命令——ping
- CetnOS下使用Eclipse开发Servlet
- fixed<<setprecision(n)
- Windows下面安装和配置MySQL(5.6.20)
- Spring_Spring_教程12_Spring利用注解实现Aop
- 使用CompletionService批处理任务
- Tomcat学习—Tomcat的tomcat-user.xml配置文件
- 【bzoj】1051 &&【poj】2186 Popular Cows Tarjan scc
- 欢迎使用CSDN-markdown编辑器
- linux Java开发工具安装与配置
- HDU 5692 Snacks
- 小K的农场 差分约束
- 练习三1021
- HDU 5694 BD String