使用ExecutorCompletionService 管理线程池处理任务的返回结果
在我们日常使用线程池的时候,经常会有需要获得线程处理结果的时候。此时我们通常有两种做法。
1. 使用并发容器将callable.call() 的返回Future存储起来。然后使用一个消费者线程去遍历这个并发容器,调用Future.isDone()去判断各个任务是否处理完毕。然后再处理响应的业务。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue; public class ExecutorResultManager { public static void main(String[] args) {
// 队列
BlockingQueue<Future<String>> futures = new LinkedBlockingQueue<>(); // 生产者
new Thread() {
@Override
public void run() {
ExecutorService pool = Executors.newCachedThreadPool(); for (int i=0; i< 10; i++) {
int index = i;
Future<String> submit = pool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "task done" + index;
}
});
try {
futures.put(submit);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start(); // 消费者
new Thread() {
@Override
public void run() {
while(true) {
for (Future<String> future : futures) {
if(future.isDone()) {
// 处理业务
// ............. };
}
}
}
}.start();
} }
2. 使用jdk 自带线程池结果管理器:ExecutorCompletionService。它将BlockingQueue 和Executor 封装起来。然后使用ExecutorCompletionService.submit()方法提交任务。
submit 方法如下:
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
// RunnableFuture封装了任务,使得任务既能run 也能get()
RunnableFuture<V> f = newTaskFor(task);
// 使用一个继承Runnable类的QueueingFutue 再次封装了我们的任务
executor.execute(new QueueingFuture(f));
return f;
}
我们再来看看QueueingFuture:
// 继承自FutureTask, FutureTask 也是一个Runnable的子类
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
// 实现了FutureTask 的done 方法,在任务处理完毕或者抛异常后将封装成Future的任务加入到队列。这样我们就能在队列中取到处处理完的任务,并通过Future.get()方法去取得处理完后的结果。不用自己去判断任务是否处理完毕了
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
简单实现:
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ExecutorCompletionServiceManager { public static void main(String[] args) { ExecutorCompletionService<String> service = new ExecutorCompletionService<String>(
Executors.newCachedThreadPool()); // 生产者
new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
int index = i;
service.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "task done" + index;
}
});
}
}
}.start(); // 消费者
new Thread() {
@Override
public void run() {
try {
Future<String> take = service.take();
// do some thing........ } catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start(); }
}
相对于原始的自造轮子处理方式,jdk 自带的工具类处理方式显得优雅了许多。
使用ExecutorCompletionService 管理线程池处理任务的返回结果的更多相关文章
- C# 多线程的自动管理(线程池) 基于Task的方式
C# 多线程的自动管理(线程池) 在多线程的程序中,经常会出现两种情况: 1. 应用程序中线程把大部分的时间花费在等待状态,等待某个事件发生,然后给予响应.这一般使用 ThreadPool(线程 ...
- C#多线程学习(四) 多线程的自动管理(线程池)
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- Solr4.8.0源码分析(3)之index的线程池管理
Solr4.8.0源码分析(3)之index的线程池管理 Solr建索引时候是有最大的线程数限制的,它由solrconfig.xml的<maxIndexingThreads>8</m ...
- Android 性能优化(16)线程优化:Creating a Manager for Multiple Threads 如何创建一个线程池管理类
Creating a Manager for Multiple Threads 1.You should also read Processes and Threads The previous le ...
- Java之线程池管理
JDK5后建议使用ExecutorService与Excutors来创建与管理线程池, 不再建议直接使用Thread. 开始不明白原因, 今天知道结果了:使用Thread.currnetThread. ...
- 深入Java线程管理(五):线程池
这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(比如 NIO),或者称为新技术吧. 线程池就是其中之一,一提到线程,我们会想到以前<操作系统>的生产者与消费者 ...
- Java 并发:Executors 和线程池
让我们开始来从入门了解一下 Java 的并发编程. 本文主要介绍如何开始创建线程以及管理线程池,在 Java 语言中,一个最简单的线程如下代码所示: Runnable runnable = new R ...
- Netty核心概念(7)之Java线程池
1.前言 本章本来要讲解Netty的线程模型的,但是由于其是基于Java线程池设计而封装的,所以我们先详细学习一下Java中的线程池的设计.之前也说过Netty5被放弃的原因之一就是forkjoin结 ...
- Java 线程池(一):开篇及Executor整体框架介绍
一.开篇 线程池.数据库连接池,在平时的学习中总能接触到这两个词,但它们到底是什么?和线程,数据库连接有什么关系?为什么需要“池”?“池”的概念及作用是什么?要弄清楚这些问题,就要深入到“池”的实现中 ...
随机推荐
- IDL 计算TVDI
介绍请看:http://blog.sina.com.cn/s/blog_764b1e9d0100wdrr.html 源码: IDL 源码PRO TVDI,NDVI,LST,NBINS,RES RES ...
- Android Studio相关的坑
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- Redis(1)在windows环境下的安装和测试
初次准备使用redis,一个著名的nosql缓存数据库. 这里是第一天,就简单写一下windows下的安装,遇到的一些问题,然后简单的使用和测试,之后会在代码中使用和测试. 之后还会在生产环境中进行测 ...
- hdu_2544_最短路(spfa版子)
题目连接:hdu_2544_最短路 存个自己写的SPFA的板子 #include<cstdio> #include<cstring> #define mst(a,b) mems ...
- storm第一篇--概念,例子,参数优化
1 概念 目前最新的0.8.0版本里面 worker -> 进程.一个worker只能执行同一个spout/bolt的task,一个worker里面可以有多个executor. executor ...
- 项目中常用js方法整理common.js
抽空把项目中常用js方法整理成了common.js,都是网上搜集而来的,大家一起分享吧. var h = {}; h.get = function (url, data, ok, error) { $ ...
- 【转】js/jquery中刷新iframe方法(兼容主流)
一.js实现刷新两种方式: 1.//方法1 2.document.getElementById('FrameID').contentWindow.location.reload(true); 3.// ...
- android studio没有浮现函数用法和属性说明?
最近转用android studio,在使用eclipse和android studio时原本在鼠标停留处或智能提示能浮现文档相关内容,但我的是一直显示Fetching Documentation…… ...
- Android音乐编程:管理音频焦点
Android 系统保持相互独立的音频流通道来播放音乐,报警,通知,来电铃声,系统声音,呼叫(通话)音量,和 DTMF 音调(键盘拨号).这样做主要是为了使用户能够独立地控制每个流的音量. AD: h ...
- dpkg -P xx
dpkg -l | grep ^rc | cut -d' ' -f3|xargs dpkg -P http://www.linuxquestions.org/questions/debian-26/h ...