CompletionService/ExecutorCompletionService/线程池/concurrent包
线程池
线程池的基本思想:线程频繁的创建、销毁会极大地占用系统资源,为了减少系统在创建销毁线程时的开销,线程池应运而生。线程池包括多个已创建的线程,当有任务要在新线程中执行时,将任务提交给线程池,线程池选取空闲线程或新开线程执行该任务,可见线程池应维护一个任务队列和线程队列。此外还要对线程最大数、最小数目、空闲等待时间等进行管理。
Executor、ExecutorService接口(线程池)
Executor提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。
方法execute()向线程池提交任务
ExecutorService接口 一个ExecutorService包括运行、关闭、终止三个生命阶段,当一个ExecutorService处于关闭状态时,不能再向线程池提交任务。线程池管理,提交任务功能扩展submit
AbstractExecutorService实现了ExecutorService接口 ,ThreadPoolExecutor、ScheduledThreadPoolExecutor类是具体的线程池实现类。
CompletionService接口、ExecutorCompletionService类
能返回已完成任务,维护一个已完成任务队列(Future),通过take() 函数可以获得任务。
CompletionService接口将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。
ExecutorCompletionService类 依赖于一个线程池对象Excutor,在一个Excutor基础上维护一个已完成任务队列。
Callable/Runnable、Future(任务接口),
(1)Callable是能够返回结果的可执行任务,Runnable不返回执行结果。文档中说Future 表示异步计算的结果,从CompletionService接口来理解,感觉不如说Future是执行完之后,包含返回结果且可以取消的任务。
(2)execute方法只能提交Runnable任务,ExecutorService接口扩展的submit方法还可以提交Callable任务,ExecutorCompletionService类的submit也支持两种任务
(3)FutrueTask实现了RunnableFuture接口,且可以由一个Callable对象来构造,基本包括了三个接口的功能
Executors(创建线程池)
类提供了用于此包中所提供的执行程序服务的工厂方法。
ExecutorCompletionService详解
ExecutorCompletionService源码
//成员变量,一个执行器,一个存放执行结果的阻塞队列
//一个ExecutorService抽象类(转化submit的Runnable或Callable为RunnableFuture<V>)
private final Executor executor;
private final AbstractExecutorService aes;
private final BlockingQueue<Future<V>> completionQueue;
//提交待执行的任务,任务均会转化为RunnableFuture<V>接口,然后放入执行器执行。
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
public Future<V> submit(Runnable task, V result) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task, result);
executor.execute(new QueueingFuture(f));
return f;
}
//内部类QueueingFuture,将转化后的RunnableFuture<V>接口对象,装配,重写done方法,使得任务执行结束后,放入完成队列
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
//阻塞方法,直至队列中有任务完成
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}
public Future<V> poll() {
return completionQueue.poll();
}
public Future<V> poll(long timeout, TimeUnit unit)
throws InterruptedException {
return completionQueue.poll(timeout, unit);
}
阻塞队列take方法源码
//用到了ReentrantLock,队列为空时await,队列使用put加元素时signal.....好一个PV操作...
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
总结
ExecutorCompletionService初始化时放入了一个线程池,并且每个submit的任务的执行结果,都会记录到本身的阻塞队列中,重点是,
如果使用take()阻塞方法取出结果的数量等于submit的任务数量,那么所有任务一定是complete(完成)。
代码示例
CompletionService<Integer> completionExecutor=new ExecutorCompletionService<>(Executors.newFixedThreadPool());
List<Task> subTasks=multiTask.getSubTasks();//假设list中有5个任务
//全部submit到ExecutorCompletionService
for (Task task : subTasks) {
completionExecutor.submit( new Runnable() {
public void run() {
task.runTask();
}
}, Integer.valueOf(TASKFINISHED));
}
//如果取任务的数量恰好是submit的数量,那么下面这段一定阻塞,直至submit的任务全部完成
for (int i = 0; i < subTasks.size(); i++) {
try {
//阻塞,直至有一个任务完成,并取回结果
Future<Integer> future=completionExecutor.take();
future.get()
} catch (InterruptedException) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
CompletionService/ExecutorCompletionService/线程池/concurrent包的更多相关文章
- Python程序中的线程操作(线程池)-concurrent模块
目录 Python程序中的线程操作(线程池)-concurrent模块 一.Python标准模块--concurrent.futures 二.介绍 三.基本方法 四.ProcessPoolExecut ...
- 进程池和线程池 concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time#线程池可以用shutdown submit from threading import current_thread from concurrent.futures impor ...
- python并发编程之进程池,线程池concurrent.futures
进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对 ...
- 创建进程池与线程池concurrent.futures模块的使用
一.进程池. 当并发的任务数量远远大于计算机所能承受的范围,即无法一次性开启过多的任务数量就应该考虑去 限制进程数或线程数,从而保证服务器不会因超载而瘫痪.这时候就出现了进程池和线程池. 二.conc ...
- concurrent包分析之Executor框架
文章目录 线程生命周期的开销:线程比较少的情况使用new Thread(task)无多大影响,但是如果涉及到线程比较多的情况,应用的性能就会受到影响,如果jdbc创建连接一样,new Thead创建线 ...
- (11)线程池(最新的concurrent.futures包去开启)
'''concurrent.futures是最新的开启线程池的包'''import timefrom concurrent.futures import ThreadPoolExecutor #开启线 ...
- 【进阶之路】线程池拓展与CompletionService操作异步任务
大家好,我是练习java两年半时间的南橘,小伙伴可以一起互相交流经验哦. 一.扩展ThreadPoolExecutor 1.扩展方法介绍 ThreadPoolExecutor是可以扩展的,它内部提供了 ...
- java多线程管理 concurrent包用法详解
我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便.而当针对高质量 ...
- java concurrent包的学习(转)
java concurrent包的学习(转) http://my.oschina.net/adwangxiao/blog/110188 我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常 ...
随机推荐
- BZOJ 3781: 小B的询问
3781: 小B的询问 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 643 Solved: 435[Submit][Status][Discuss ...
- Mysql 查询练习
Mysql 查询练习 ---创建班级表 create table class( cid int auto_increment primary key, caption ) )engine=innodb ...
- PHP文件大小格式化函数合集
比如碰到一个很大的文件有49957289167B,大家一看这么一长串的数字后面单位是字节B,还是不知道这个文件的大小是一个什么概念,我们把它转换成GB为单位,就是46.53GB.用下面这些函数就可以完 ...
- python2-gst0.10制作静态包的补丁 v1.1
gst制作成了静态库,而python2的gst有多个动态库引用gst的库 因此,想了一个办法将python2所需要的gst打包成一个单独的共享库 办法就是,将python2_gst所有的.so先制作成 ...
- Jquery动态添加的元素绑定事件的3种方法
假设我们点击li标签,弹出他的文本,如果是动态添加的li,点击是没有效果的,压根弹不出来文本. 下面博主分享一下为动态添加的元素绑定事件的三种方法,网上一般都是两种,我在这里多增加了一种. 事件案例: ...
- 如何夯实(Java)编程基础,并深入学习和提高
如何夯实(Java)编程基础,并深入学习和提高? 240赞同反对,不会显示你的姓名 匿名用户 240 人赞同 多学习...网上自学的学习网站很多,见以下榜单~一.汇总榜单: 公开课_学习网站导航 收录 ...
- 树莓派2安装使用小米WIfi(360 小度 腾讯wifi)
更新2015年11月16日,jessie内核版本号4.1.13(uname -a 可以查看)直接可以驱动MT7601U,无需手动编译. 截止2015-4-6,本文基于树莓派2,raspbian,内核版 ...
- Eclipse DDT
http://www.eclipse.org/downloads/ https://github.com/DDT-IDE/DDT/blob/latest/documentation/UserGuide ...
- C C++ 语法
非常酷的网站: http://yige.org/cpp/defined_data_types.php 在Linux下有一个目录/proc/$(pid),这个目录保存了进程号为pid的进程运行时的所有信 ...
- [NHibernate]一对多关系(级联删除,级联添加)
目录 写在前面 文档与系列文章 一对多关系 一个例子 级联删除 级联保存 总结 写在前面 在前面的文章中,我们只使用了一个Customer类进行举例,而在客户.订单.产品中它们的关系,咱们并没有涉及, ...