如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果,怎么办呢?

为此你可以保存与每个任务相关联的Future,然后不断地调用 timeout为零的get,来检验Future是否完成。这样做固然可以,但却相当乏味。幸运的是,还有一个更好的方法:完成服务 (Completion service)。

CompletionService整合了Executor和BlockingQueue的功能。

你可以将Callable任务提交给它去执行,然 后使用类似于队列中的take和poll方法,在结果完整可用时获得这个结果,像一个打包的Future。 ExecutorCompletionService是实现CompletionService接口的一个类,并将计算任务委托给一个Executor。

ExecutorCompletionService的实现相当直观。它在构造函数中创建一个BlockingQueue,用它去保持完成的结果。 计算完成时会调用FutureTask中的done方法。

当提交一个任务后,首先把这个任务包装为一个QueueingFuture,它是 FutureTask的一个子类,然后覆写done方法,将结果置入BlockingQueue中,take和poll方法委托给了 BlockingQueue,它会在结果不可用时阻塞。

直接看demo:

package javademo;

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;

/***

* 两钟方式出来线程运行结果

* @author think

*

*/

public class CompletionServiceTest {

public static void main(String[] args) throws Exception {

CompletionServiceTest cst = new CompletionServiceTest();

cst.count1();

cst.count2();

}

/***

* 使用阻塞容器保存每次Executor处理的结果,在后面进行统一处理

* @throws Exception

*/

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处理的结果

* @throws InterruptedException

* @throws ExecutionException

*/

public void count2() throws InterruptedException, ExecutionException{

ExecutorService exec = Executors.newCachedThreadPool();

CompletionService<Integer> execcomp = new ExecutorCompletionService<Integer>(exec);

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();

}

/**

* 得到一个任务

* @return Callable

*/

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;

}

}

  1. import java.util.Random;
  2. import java.util.concurrent.BlockingQueue;
  3. import java.util.concurrent.Callable;
  4. import java.util.concurrent.CompletionService;
  5. import java.util.concurrent.ExecutionException;
  6. import java.util.concurrent.ExecutorCompletionService;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;
  10. import java.util.concurrent.LinkedBlockingQueue;
  11. public class Test17 {
  12. public static void main(String[] args) throws Exception {
  13. Test17 t = new Test17();
  14. t.count1();
  15. t.count2();
  16. }
  17. //使用阻塞容器保存每次Executor处理的结果,在后面进行统一处理
  18. public void count1() throws Exception{
  19. ExecutorService exec = Executors.newCachedThreadPool();
  20. BlockingQueue<Future<Integer>> queue = new LinkedBlockingQueue<Future<Integer>>();
  21. for(int i=0; i<10; i++){
  22. Future<Integer> future =exec.submit(getTask());
  23. queue.add(future);
  24. }
  25. int sum = 0;
  26. int queueSize = queue.size();
  27. for(int i=0; i<queueSize; i++){
  28. sum += queue.take().get();
  29. }
  30. System.out.println("总数为:"+sum);
  31. exec.shutdown();
  32. }
  33. //使用CompletionService(完成服务)保持Executor处理的结果
  34. public void count2() throws InterruptedException, ExecutionException{
  35. ExecutorService exec = Executors.newCachedThreadPool();
  36. CompletionService<Integer> execcomp = new ExecutorCompletionService<Integer>(exec);
  37. for(int i=0; i<10; i++){
  38. execcomp.submit(getTask());
  39. }
  40. int sum = 0;
  41. for(int i=0; i<10; i++){
  42. //检索并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。
  43. Future<Integer> future = execcomp.take();
  44. sum += future.get();
  45. }
  46. System.out.println("总数为:"+sum);
  47. exec.shutdown();
  48. }
  49. //得到一个任务
  50. public Callable<Integer> getTask(){
  51. final Random rand = new Random();
  52. Callable<Integer> task = new Callable<Integer>(){
  53. @Override
  54. public Integer call() throws Exception {
  55. int i = rand.nextInt(10);
  56. int j = rand.nextInt(10);
  57. int sum = i*j;
  58. System.out.print(sum+"\t");
  59. return sum;
  60. }
  61. };
  62. return task;
  63. }
  64. /**
  65. * 执行结果:
  66. 6   6   14  40  40  0   4   7   0   0   总数为:106
  67. 12  6   12  54  81  18  14  35  45  35  总数为:312
  68. */
  69. }

Java线程之CompletionService批处理任务的更多相关文章

  1. Java线程之CompletionService

    转自:http://blog.csdn.net/andycpp/article/details/8902699 当使用ExecutorService启动了多个Callable后,每个Callable会 ...

  2. Java线程之 InterruptedException 异常

    Java线程之 InterruptedException 异常   当一个方法后面声明可能会抛出InterruptedException 异常时,说明该方法是可能会花一点时间,但是可以取消的方法. 抛 ...

  3. java 线程之executors线程池

    一.线程池的作用 平时的业务中,如果要使用多线程,那么我们会在业务开始前创建线程,业务结束后,销毁线程.但是对于业务来说,线程的创建和销毁是与业务本身无关的,只关心线程所执行的任务.因此希望把尽可能多 ...

  4. java 线程之concurrent中的常用工具 CyclicBarrier

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  5. C++/Java线程之分

    JAVA线程状态图 1.C++/windows中主线程结束,其他线程必然死亡(即使调用pthread_detach解除父子关系,主线程消亡时也会导致子线程被迫关闭). ----1.1 一个进程中可以有 ...

  6. Java线程之Callable和Future

    本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果.        Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结 ...

  7. Java线程之Synchronized用法

    synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对 ...

  8. Java线程之Java内存模型(jmm)

    一.Java内存模型(jmm) 线程通信 消息传递 重排序 顺序一致性 Happens-Before As-If-Serial

  9. Java线程之Dump

    什么是线程dump Java Thread dump记录了线程在jvm中的执行信息,可以看成是线程活动的日志.Java线程转储文件有助于分析应用程序和死锁情况中的瓶颈. 如何获取线程转储文件 在这里, ...

随机推荐

  1. 无法启动此程序因为计算机中丢失 xxx.dll

    “无法启动此程序因为计算机中丢失 XXX.dll” 这类问题在 visual studio 中很常见… 许久不和VS打交道,一碰各种坑… 这是在 VS 2015 Community 出现的问题: (1 ...

  2. Android上怎样使用《贝赛尔曲线》

    首先对于<赛贝尔曲线>不是很了解的童鞋,请自觉白度百科.google. 为了方便偷懒的童鞋,这里给个<贝赛尔曲线>百科地址,以及一段话简述<贝赛尔曲线>: < ...

  3. c# 高效的线程安全队列ConcurrentQueue

    c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...

  4. 跨服务器查询信息的sql

    --跨服务器查询信息的sql: select * from openrowset( 'SQLOLEDB', '192.168.1.104'; 'sa'; '123.com',[AutoMonitorD ...

  5. CentOS中安装JDK与Intellij idea

    卸载CentOS中自带openjdk CentOS自带openjdk,可以先用java –version检测是否存在jdk版本.如果存在,最好在安装oracle的jdk之前最好卸载,可以使用如下指令 ...

  6. [svc]tomcat配置文件详解

    Tomcat系列之服务器的安装与配置以及各组件详解 tomcat 配置文件详解 tomcat安全管理规范

  7. 每日英语:How to find the career of your dreams

    The fate described by Dostoyevsky is a nightmare we all hope to escape. But we're surrounded by nays ...

  8. nyoj 952 最大四边形 计算几何 转载

    事实再一次证明:本小菜在计算几何上就是个渣啊,唉,,, 题意:平面上n个点(n<=300),问任意四个点组成的四边形(保证四条边不相交)的最大面积是多少. 分析: 原文地址 1.第一思路是枚举四 ...

  9. jquery $.each 和for 怎么跳出循环(终止本次循环)

    1.for循环中我们使用continue:终止本次循环计入下一个循环,使用break终止整个循环. 2.而在jquery中 $.each则对应的使用return true  和return false ...

  10. jsp页面和js代码中使用sessionScope获取session值

    场景:有些实体对象可以放到HttpSession对象中,保正在一个会话期间可以随时获取这个对象的属性,例如可以将登录用户的信息写入session,以保证页面随时可以获取并显示这个用户的状态信息.下面以 ...