Executor 框架详解
框架最核心的类是ThreadPoolExecutor
,它是Java线程池的实现类,通过Executors
工具类,可以创建3种类型的ThreadPoolExecutor
:
首先附上ThreadPoolExecutor
的构造函数
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
FixedThreadPool
可重用固定线程数的线程池。实现源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
在这里,corePoolSize
和maximumPoolSize
都设置成了创建时指定的线程数nThread
,当线程池中的线程数大于corePoolSize
时,keepAliveTime
为多余的空闲线程等待新任务的时间,超过这个时间后线程将会被终止。在这里设置为0L,意味着多余的空闲线程将会被立即终止。
FixedPoolThread
的execute()
方法运行流程如下:
- 如果当前运行的线程少于
corePoolSize
,则创建新的线程来执行任务。 - 在线程池完成预热之后(当前运行的线程数等于
corePoolSize
),将任务加入LinkedBlockingQueue
- 线程执行完1中的任务后,会在循环中反复从
LinkedBlockingQueue
获取任务来执行
由于它采用了LinkedBlockingQueue
来作为线程池的工作队列,这是一个无界队列(队列容量为Integer.MAX_VALUE
)。所以将会为线程池带来如下影响:
当线程池的线程数达到
corePoolSize
之后,新的任务将会在无界队列中等待,因此线程池中的线程不会超过corePoolSize
由于1,使用无界队列时
maximumPoolSize
将是一个无效参数;由于1和2,使用无界队列时
keepAliveTime
将是一个无效参数由于使用无界队列,运行中的
FixedThreadPool
(未执行shutdown()或shutdownNow())不会拒绝任务。
SingleThreadExecutor
使用单个worker线程的Executor,下面是源码实现:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
SingleThreadExecutor
的corePoolSize
和maximumPoolSize
都被设置成1,其他参数则与FixedThreadPool
相同,它使用无界队列的影响与FixedThreadPool
是同样的。下面是它的运行流程图:
- 如果当前没有线程在运行,则创建一个新的线程
- 当线程池中有且仅有一个运行的线程,将任务加入
LinkedBlockingQueue
- 线程执行完1中的任务后,会在循环中反复从
LinkedBlockingQueue
获取任务执行。
CachedThreadPool
一个会根据需要创建新线程的线程池,下面是源码实现:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
它的corePoolSize
被设置为0,maximumPoolSize
设置为Integer.MAX_VALUE
,即maximumPool
是无界的;把keepAliveTime
设置成60L,意味着该线程池中空闲线程等待新任务的最长时间为60秒,超时则被会终止。CachedThreadPool
使用没有容量的SynchronousQueue
作为线程池的工作队列,但CachedThreadPool
的maximumPool
是无界的,意味着,如果主线程提交任务的速度高于maximumPool
中线程处理的速度,它将会不断的创建新的线程,直到耗尽所有CPU和内存资源。它的运行流程如图:
- 首先执行
SynchronousQueue.offer(task)
,如果当前maximumPool
中有空闲线程正在执行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)
,那么主线程执行的offer
操作与空闲线程执行的poll
操作配对成功,主线程把任务交给空闲线程执行,execute
执行成功,否则执行下面的操作。 - 当
maximumPool
为空,或者其中没有空闲线程时,将没有线程执行poll
操作,那么CachedThreadPool
会创建一个新的线程,execute
方法执行成功。 - 在上面的步骤中,线程将任务执行完后,变为空闲状态,将会执行
poll
操作,空闲线程继续等待新的任务到来并配对执行,如果超过60s,则线程将会被终止。由于超过60秒的空闲线程将会被终止,所以长时间保持空闲的CachedThreadPool
不会使用任何资源。
CachedThreadPool的任务传递示意图:
ScheduledThreadPoolExecutor
主要用来在给定的延迟之后运行任务,或者定期执行任务,下面是源码实现:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
该类直接继承自ThreadPoolExecutor
,为的是能直接使用已经实现的方法,而且,它新加了几个方法:
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
//向定时任务线程池提交一个延时Runnable任务(仅执行一次)public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit);
//向定时任务线程池提交一个延时的Callable任务(仅执行一次)public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,long period, TimeUnit unit)
//向定时任务线程池提交一个固定时间间隔执行的任务public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,long delay, TimeUnit unit);
//向定时任务线程池提交一个固定延时间隔执行的任务
也可以向其直接提交普通任务,相当于延时和周期都为0的任务。这里构造时的数值含义与前面的类似,就不赘述了。下面是基本运行流程图:
- 主线程提交普通任务或有延时或周期的任务。并将任务加入具有优先性质的阻塞队列。
- 线程池中的线程每次通过
take()
方法获取任务,然后从任务的getDelay()
方法获取应当延时的时间,当延时达到,执行任务。执行完毕后,判断这是不是一个周期任务,如果是,则继续延时执行任务,如果不是,则继续调用take方法获取任务,如果没有获取到任务,空闲线程将会被终止。
FutureTask
代表异步计算的结果,根据FutureTask.run()方法执行状况,可以分为下面三种状态:
- 未启动:FutureTask.run()方法还没有被执行前
- 已启动:FutureTask.run()方法正在执行
- 已完成:FutureTask.run()方法正常结束、被取消、执行抛出异常、异常结束
下面是FutureTask对应get(),cancel()方法执行示意图:
Executor 框架详解的更多相关文章
- 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术
这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...
- java高并发系列 - 第20天:JUC中的Executor框架详解2之ExecutorCompletionService
这是java高并发系列第20篇文章. 本文内容 ExecutorCompletionService出现的背景 介绍CompletionService接口及常用的方法 介绍ExecutorComplet ...
- mina框架详解
转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...
- Spark2.1.0——内置Web框架详解
Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...
- jQuery Validate验证框架详解
转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...
- lombok+slf4j+logback SLF4J和Logback日志框架详解
maven 包依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lomb ...
- [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解
Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...
- iOS 开发之照片框架详解(2)
一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...
- Quartz.NET作业调度框架详解
Quartz.NET作业调度框架详解 http://www.cnblogs.com/lmule/archive/2010/08/28/1811042.html
随机推荐
- Linq 使用skip和take分页
static int Main(string[] args) { //每页条数 const int pageSize = 2; //页码 0就是第一条数据 int pageNum = 0; strin ...
- 测序中Q20 Q30 Q40
你能给别人讲清楚这个概念吗? 二代测序中,每测一个碱基会给出一个相应的质量值,这个质量值是衡量测序准确度的.碱基的质量值13,错误率为5%,20的错误率为1%,30的错误率为0.1%.行业中Q20与Q ...
- LeetCode--121--卖卖股票的最佳时机
问题描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出 ...
- UVA557 汉堡 Burger
题面 https://www.luogu.org/problemnew/show/UVA557 这里顺便整理一下二维格点随机游走问题. 遇到这种问题时,需注意分母的计算问题. 设x为起点到终点的距离. ...
- President's Path CodeForces - 416E (最短路,计数)
大意: 给定无向图, 求任意两点间所有最短路经过的边数 刚开始想先用floyd跑出最短路, 然后在DAG上DP, 交了1发, 发现会算重复 贴一下题解的做法 #include <iostream ...
- cf188C(最大子段和&&思维)
C. Functions again time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- mac连接Windows远程桌面
先打开微软官方的下载面面:http://www.microsoft.com/zh-CN/download/details.aspx?id=18140 下载远程连接客户端 http://jingyan. ...
- dubbo 心跳
HeartBeatTask 类封装了心跳定时任务,需要了解的是 provider 和 consumer 都有可能发送心跳. final class HeartBeatTask implements R ...
- java并发编程:线程安全管理类--原子操作类--AtomicLongFieldUpdater<T>
1.类 AtomicLongFieldUpdater<T> public abstract class AtomicLongFieldUpdater<T> extends Ob ...
- Java live template[在此处输入文章标题]
Java -Dfile.encoding=UTF-8 提示键盘 功能 Logg private final Logger log = Logger.getLogger(this.getClass()) ...