如果你向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. ABP 3.7版本迁移数据库报错未能加载文件或程序集“Castle.Core, Version=4.0.0.0”

    ABP 3.7 3.8版本升级后迁移数据库,报错未能加载文件或程序集“Castle.Core, Version=4.0.0.0”,System.ComponentModel.Annotations也可 ...

  2. webpack 配置之入门二(css 篇)

    在项目中我们通过 css 来美化页面,css 也成为了网站不可或缺的一部分,这章节主要介绍 webpack 处理 css 部分, 1.webpack 处理 css 在 webpack 中,我们通过 s ...

  3. dubbo源码学习(二) : spring 自定义标签

    做dubbo的配置时很容易发现,dubbo有一套自己的标签,提供给开发者配置,其实每一个标签对应着一个 实体,在容器启动的时候,dubbo会对所有的配置进行解析然后将解析后的内容设置到实体里,最终du ...

  4. javascript基础入门之js中的数据类型与数据转换01

    javascript基础入门之js中的数据结构与数据转换01 js的组成(ECMAScript.BOM.DOM)        js中的打印语句:        数据类型        变量      ...

  5. wchar用wcout输出正常cout是?

  6. 由 15.01升级到 16.04之后,无法启动mysql

    参考 16.04 Distribution Upgrade - cannot start MySQL server,然后找到了16.04 upgrade broke mysql-server 我由 1 ...

  7. jenkins的安装和启用

    1.下载Jenkins:下载地址:https://jenkins.io/zh/download/ 2.将Jenkins.war包上传到Tomcat的webapps目录下,本次的目录是/usr/loca ...

  8. break , continue 和 标签 跳出循环

    break跳出代码块或循环 var i = 0: while ( i <= 10){ console.log(' i '); i ++; if ( i === 5 ) break; }// 0 ...

  9. AbstractQueuedSynchronizer 详解

    package java.util.concurrent.locks; 基本介绍 AbstractQueuedSynchronizer(队列同步器)可以看作是并发包(java.util.concurr ...

  10. 在线暴躁:<script />问题

    这个问题是今天发现的,以前都没注意到这个问题: <script src="./vue/vue.min.js" /> <script src="./vue ...