如果你向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,它会在结果不可用时阻塞。

 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);
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
*/
}

ExecutorCompletionService统一了ExecutorService和BlockingQueue,既有线程池功能,能提交任务,又有阻塞队列功能,能判断所有线程的执行结果。

使用CompletionService批处理任务(线程池阻塞线程)的更多相关文章

  1. 由浅入深理解Java线程池及线程池的如何使用

    前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...

  2. ReentrantLock+线程池+同步+线程锁

    1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...

  3. 根据CPU核心数确定线程池并发线程数

    一.抛出问题 关于如何计算并发线程数,一般分两派,来自两本书,且都是好书,到底哪个是对的?问题追踪后,整理如下: 第一派:<Java Concurrency in Practice>即&l ...

  4. 高并发的epoll+线程池,线程池专注实现业务

    我们知道,服务器并发模型通常可分为单线程和多线程模型,这里的线程通常是指“I/O线程”,即负责I/O操作,协调分配任务的“管理线程”,而实际的请求和任务通常交由所谓“工作者线程”处理.通常多线程模型下 ...

  5. Java多线程系列 JUC线程池03 线程池原理解析(二)

    转载  http://www.cnblogs.com/skywang12345/p/3509954.html  http://www.cnblogs.com/skywang12345/p/351294 ...

  6. Java多线程系列 JUC线程池02 线程池原理解析(一)

    转载  http://www.cnblogs.com/skywang12345/p/3509960.html ; http://www.cnblogs.com/skywang12345/p/35099 ...

  7. Java多线程系列 JUC线程池01 线程池框架

    转载  http://www.cnblogs.com/skywang12345/p/3509903.html 为什么引入Executor线程池框架 new Thread()的缺点 1. 每次new T ...

  8. 异步线程编程,线程池,线程组,后面涉及ThreadLocal在理解

    join模拟订单 package com.future.demo.future; /** * * * @author Administrator * */ public class NormalThr ...

  9. java并发编程(十七)----(线程池)java线程池架构和原理

    前面我们简单介绍了线程池的使用,但是对于其如何运行我们还不清楚,Executors为我们提供了简单的线程工厂类,但是我们知道ThreadPoolExecutor是线程池的具体实现类.我们先从他开始分析 ...

随机推荐

  1. Mysql 命令行下建立存储过程

    建立存储过程的sql如下: CREATE PROCEDURE  proc_variable () BEGIN DECLARE dec_var_ VARCHAR(100); DECLARE rep_nu ...

  2. 教你如何有效防止DDos攻击?

    DDos又称分布式拒绝服务,DDos是利用大量合理的请求造成资源过载,导致服务不可用.就比如一个餐馆总共有100个座位,突然有一天某个商家恶意竞争,雇佣了200个人来到这个餐馆坐着不吃不喝,门口还排着 ...

  3. pyJWT

    现在用JWT 加密太火了,怎么能不跟上潮流?否则销售都不好意思出去吹牛逼! PyJWT是一个Python库,用来编码/解码JWT(JSON Web Token)的 1.定义:根据维基百科的定义,JSO ...

  4. Operator '?:' has lower precedence than '*'; '*' will be evaluated first

    1.项目中用宏的时候,遇到如下警告 Operator '?:' has lower precedence than '*'; '*' will be evaluated first 2.错误原因 *操 ...

  5. activeMQ的回顾

    JMS: JMS基本概念: JMS(Java Message Service) 即Java消息服务.它提供标准的产生.发送.接收消息的接口简化企业应用的开发.它支持两种消息通信模型:点到点(point ...

  6. selenium如何操作页面树状列表

    selenium如何操作页面树状列表??举个例子:我要怎么操作如下图所示的树状结构列表?我要对这个树状结构列表做什么操作? 一.思路 1.根据driver.find_element_by_xpath( ...

  7. 34. Thread类的常用方法

    1.构造方法 Thread() 分配新的 Thread 对象. Thread(String name)  分配新的 Thread 对象并指定线程名字 2.方法 1)setName(String nam ...

  8. 在小程序中引入有赞的vant框架组件

    这里给大家讲解小程序中如何引入vant组件(我这里是采用小程序的云开发模板) 1.首先在项目的miniprogram文件夹右键在终端中打开,输入命令npm init初始化生成一个package.jso ...

  9. 【RabbitMQ】六种模式与SpringBoot整合

    添加rabbitmq的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  10. 去除springboot内置tomcat

    /** * @author zx * @title: ServletInitializer * @projectName activiti * @description: 解决内置tomcat * @ ...