ThreadPoolExecutor执行过程分析
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:线程池核心线程数(平时保留的线程数)
- maximumPoolSize:线程池最大线程数(当workQueue都放不下时,启动新线程,最大线程数)
- keepAliveTime:超出corePoolSize数量的线程的保留时间。
- unit:keepAliveTime单位
workQueue:阻塞队列,存放来不及执行的线程
- ArrayBlockingQueue:构造函数一定要传大小
- LinkedBlockingQueue:构造函数不传大小会默认为65536(Integer.MAX_VALUE ),当大量请求任务时,容易造成 内存耗尽。
- SynchronousQueue:同步队列,一个没有存储空间的阻塞队列 ,将任务同步交付给工作线程。
- PriorityBlockingQueue : 优先队列
- threadFactory:线程工厂
handler:饱和策略
- AbortPolicy(默认):直接抛弃
- CallerRunsPolicy:用调用者的线程执行任务
- DiscardOldestPolicy:抛弃队列中最久的任务
- DiscardPolicy:抛弃当前任务
ThreadPoolExecutor 测试代码
//test.java
volatile int finishState = 0;
@Test
public void test4() throws InterruptedException, ExecutionException {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 7, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10));
ExecutorCompletionService<String> executorCompletionService = new ExecutorCompletionService(threadPoolExecutor);
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
String name = "name_" + i;
TestCallable testCallable = new TestCallable(name);
try {
executorCompletionService.submit(testCallable);
synchronized (lock) {
System.out.print("+++添加任务 name: " + name);
System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());
}
} catch (RejectedExecutionException e) {
synchronized (lock) {
System.out.println("拒绝:" + name);
}
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
finishState = 1;
}
};
Thread addThread = new Thread(runnable);
addThread.start();
//System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());
//添加的任务有被抛弃的。taskCount不一定等于添加的任务。
int completeCount = 0;
while (!(completeCount == threadPoolExecutor.getTaskCount() && finishState == 1)) {
Future<String> take = executorCompletionService.take();
String taskName = take.get();
synchronized (lock) {
System.out.print("---完成任务 name: " + taskName);
System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
System.out.print(" taskCount: " + threadPoolExecutor.getTaskCount());
System.out.println(" finishTask:" + (++completeCount));
}
}
addThread.join();
while (threadPoolExecutor.getPoolSize() > 0) {
Thread.sleep(1000);
synchronized (lock) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
System.out.print(simpleDateFormat.format(new Date()));
//System.out.print("name: " + taskName);
System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());
}
}
// Tell threads to finish off.
threadPoolExecutor.shutdown();
// Wait for everything to finish.
while (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
System.out.println("complete");
}
}
//TestCallable.java
public class TestCallable implements Callable<String>{
private String name;
public TestCallable(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.name;
}
}
执行结果
+++添加任务 name: name_0 ActiveCount: 1 poolSize: 1 queueSize: 0 taskCount: 1
+++添加任务 name: name_1 ActiveCount: 2 poolSize: 2 queueSize: 0 taskCount: 2
+++添加任务 name: name_2 ActiveCount: 3 poolSize: 3 queueSize: 0 taskCount: 3
//corePoolSize=3,所以poolSize逐渐加到3.
+++添加任务 name: name_3 ActiveCount: 3 poolSize: 3 queueSize: 1 taskCount: 4
+++添加任务 name: name_4 ActiveCount: 3 poolSize: 3 queueSize: 2 taskCount: 5
+++添加任务 name: name_5 ActiveCount: 3 poolSize: 3 queueSize: 3 taskCount: 6
+++添加任务 name: name_6 ActiveCount: 3 poolSize: 3 queueSize: 4 taskCount: 7
+++添加任务 name: name_7 ActiveCount: 3 poolSize: 3 queueSize: 5 taskCount: 8
+++添加任务 name: name_8 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 9
+++添加任务 name: name_9 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 10
---完成任务 name: name_0 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 10 finishTask:1
+++添加任务 name: name_10 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 11
---完成任务 name: name_1 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 11 finishTask:2
+++添加任务 name: name_11 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 12
---完成任务 name: name_2 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 12 finishTask:3
+++添加任务 name: name_12 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 13
+++添加任务 name: name_13 ActiveCount: 3 poolSize: 3 queueSize: 8 taskCount: 14
+++添加任务 name: name_14 ActiveCount: 3 poolSize: 3 queueSize: 9 taskCount: 15
+++添加任务 name: name_15 ActiveCount: 3 poolSize: 3 queueSize: 10 taskCount: 16
//因为任务队列为:new LinkedBlockingDeque<>(10),core线程不够用时,将任务添加到队列中。
//queueSize到10,队列已满。开始增加poolSize,加到maximumPoolSize=7
+++添加任务 name: name_16 ActiveCount: 4 poolSize: 4 queueSize: 10 taskCount: 17
+++添加任务 name: name_17 ActiveCount: 5 poolSize: 5 queueSize: 10 taskCount: 18
+++添加任务 name: name_18 ActiveCount: 6 poolSize: 6 queueSize: 10 taskCount: 19
+++添加任务 name: name_19 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 20
---完成任务 name: name_3 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 20 finishTask:4
+++添加任务 name: name_20 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 21
---完成任务 name: name_4 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 21 finishTask:5
+++添加任务 name: name_21 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 22
---完成任务 name: name_5 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 22 finishTask:6
+++添加任务 name: name_22 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 23
//poolSize=maximumPoolSize,queueSize=10,都满了。执行饱和策略。默认AbortPolicy抛弃新任务。
拒绝:name_23
拒绝:name_24
拒绝:name_25
---完成任务 name: name_16 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 23 finishTask:7
+++添加任务 name: name_26 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 24
---完成任务 name: name_17 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 24 finishTask:8
+++添加任务 name: name_27 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 25
---完成任务 name: name_18 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 25 finishTask:9
+++添加任务 name: name_28 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 26
---完成任务 name: name_19 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 26 finishTask:10
+++添加任务 name: name_29 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 27
---完成任务 name: name_6 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 27 finishTask:11
+++添加任务 name: name_30 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 28
---完成任务 name: name_7 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 28 finishTask:12
+++添加任务 name: name_31 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 29
---完成任务 name: name_8 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 29 finishTask:13
+++添加任务 name: name_32 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 30
拒绝:name_33
拒绝:name_34
拒绝:name_35
---完成任务 name: name_9 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 30 finishTask:14
+++添加任务 name: name_36 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 31
---完成任务 name: name_10 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 31 finishTask:15
+++添加任务 name: name_37 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 32
---完成任务 name: name_11 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 32 finishTask:16
+++添加任务 name: name_38 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 33
---完成任务 name: name_12 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 33 finishTask:17
+++添加任务 name: name_39 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 34
---完成任务 name: name_13 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 34 finishTask:18
+++添加任务 name: name_40 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 35
---完成任务 name: name_14 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 35 finishTask:19
+++添加任务 name: name_41 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 36
---完成任务 name: name_15 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 36 finishTask:20
+++添加任务 name: name_42 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 37
拒绝:name_43
拒绝:name_44
拒绝:name_45
---完成任务 name: name_20 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 37 finishTask:21
+++添加任务 name: name_46 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 38
---完成任务 name: name_21 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 38 finishTask:22
+++添加任务 name: name_47 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 39
---完成任务 name: name_22 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 39 finishTask:23
//消费速度大于添加速度,poolSize并不减少,先把queue中的任务逐一执行完成。
+++添加任务 name: name_48 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 40
---完成任务 name: name_26 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 40 finishTask:24
---完成任务 name: name_27 ActiveCount: 7 poolSize: 7 queueSize: 8 taskCount: 40 finishTask:25
+++添加任务 name: name_49 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 41
---完成任务 name: name_28 ActiveCount: 7 poolSize: 7 queueSize: 8 taskCount: 41 finishTask:26
---完成任务 name: name_29 ActiveCount: 7 poolSize: 7 queueSize: 7 taskCount: 41 finishTask:27
---完成任务 name: name_30 ActiveCount: 7 poolSize: 7 queueSize: 6 taskCount: 41 finishTask:28
---完成任务 name: name_31 ActiveCount: 7 poolSize: 7 queueSize: 5 taskCount: 41 finishTask:29
---完成任务 name: name_32 ActiveCount: 7 poolSize: 7 queueSize: 4 taskCount: 41 finishTask:30
---完成任务 name: name_36 ActiveCount: 7 poolSize: 7 queueSize: 3 taskCount: 41 finishTask:31
---完成任务 name: name_37 ActiveCount: 7 poolSize: 7 queueSize: 2 taskCount: 41 finishTask:32
---完成任务 name: name_38 ActiveCount: 7 poolSize: 7 queueSize: 1 taskCount: 41 finishTask:33
---完成任务 name: name_39 ActiveCount: 7 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:34
//ActiveCount开始减少。
---完成任务 name: name_40 ActiveCount: 6 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:35
---完成任务 name: name_41 ActiveCount: 5 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:36
---完成任务 name: name_42 ActiveCount: 4 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:37
---完成任务 name: name_46 ActiveCount: 3 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:38
---完成任务 name: name_47 ActiveCount: 2 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:39
---完成任务 name: name_48 ActiveCount: 1 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:40
---完成任务 name: name_49 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:41
22:47:49 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:50 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:51 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:52 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:53 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:54 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:55 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:56 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:57 ActiveCount: 0 poolSize: 5 queueSize: 0 taskCount: 41
//由于keepAliveTime=10,大概10s后poolSize恢复为corePoolSize。
22:47:58 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41
22:47:59 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41
22:48:00 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41
注意
《阿里巴巴java开发手册》
线程池不使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors 返回的线程池对象的弊端如下:
- FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。
- CachedThreadPool 和 ScheduledThreadPool : 允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。
Reference
ThreadPoolExecutor执行过程分析的更多相关文章
- 并发包的线程池第一篇--ThreadPoolExecutor执行逻辑
学习这个很长时间了一直没有去做个总结,现在大致总结一下并发包的线程池. 首先,任何代码都是解决问题的,线程池解决什么问题? 如果我们不用线程池,每次需要跑一个线程的时候自己new一个,会导致几个问题: ...
- ASP.NET MVC应用程序执行过程分析
ASP.NET MVC应用程序执行过程分析 2009-08-14 17:57 朱先忠 朱先忠的博客 字号:T | T ASP.NET MVC框架提供了支持Visual Studio的工程模板.本文 ...
- Ansible系列(七):执行过程分析、异步模式和速度优化
本文目录:1.1 ansible执行过程分析1.2 ansible并发和异步1.3 ansible的-t选项妙用1.4 优化ansible速度 1.4.1 设置ansible开启ssh长连接 1.4. ...
- MFC的执行过程分析
MFC程序的执行细节剖析 MFC程序也是Windows程序,所以它应该也有一个WinMain.可是在程序中看不到它的踪影.事实上在程序进入点之前.另一个(并且仅有一个)全局对象(theApp).这就是 ...
- ThreadPoolExecutor执行任务,异常日志缺失问题
之前在使用自定义线程池异步执行耗时任务时,一直记着如果业务方法抛出异常没有捕获,那么是看不到日志框架输出的异常日志的,所以总是在业务方法中包裹一层try-catch捕获可能发生的异常.也未去深入为什么 ...
- CDH集群spark-shell执行过程分析
目的 刚入门spark,安装的是CDH的版本,版本号spark-core_2.11-2.4.0-cdh6.2.1,部署了cdh客户端(非集群节点),本文主要以spark-shell为例子,对在cdh客 ...
- http执行过程分析
执行过程: 1.用户在浏览器(客户端)里输入或者点击一个网址链接: 2.浏览器通过网址域名查找ip地址.DNS查找方式是通过浏览器缓存(会记录DNS记录)→系统缓存→TCP/IP参数中设置的首选DNS ...
- twitter storm源码走读之6 -- Trident Topology执行过程分析
欢迎转载,转载请注明出处,徽沪一郎. TridentTopology是storm提供的高层使用接口,常见的一些SQL中的操作在tridenttopology提供的api中都有类似的影射.关于Tride ...
- u-boot、kernel和filesystem 执行过程分析
标题: Uboot -kerne-root 启动流程 内容: ※uboot启动流程 ※Kernel启动流程 ※Root启动流程 ※构建根文件系统 /************************** ...
随机推荐
- 【点击模型学习笔记】Modeling contextual factors of click rates_MS_AAAI2007
概要 并没有觉得这是篇高质量的文章,非常奇怪为什么可以发表在AAAI上面. 文章的创新点比較单薄:在传统点击率预測模型(LR)的基础上增加了两类新的特征,一个是位置特征.一个是广告上下文特征--即和它 ...
- 前端写一个月的原生 Android 是如何一种体验?
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/j01G58UC80251/article/details/79017706 一个前端程序猿的一个月原 ...
- vue.js常用的
<input v-model.number="age" type="number"> //自动将用户的输入值转为数值类型 <input v-m ...
- Linux中Kill掉进程的10种方法
常规篇: 首先,用ps查看进程,方法如下: 复制代码 代码如下: $ ps -ef……smx 1822 1 0 11:38 ? 00:00:49 gnome-terminalsmx 1823 1822 ...
- selenium webdriver testng自动化测试数据驱动
selenium webdriver testng自动化测试数据驱动 selenium webdriver testng自动化测试数据驱动 一.数据驱动测试概念 数据驱动测试是相同的测试脚本使用不同的 ...
- http 之 HTTP_X_FORWARDED_FOR
原文 http://www.imququ.com/post/x-forwarded-for-header-in-http.html 主题 HTTP Nginx 我一直认为,对于从事 Web 前端开 ...
- Ants-穷举算法
package java操作excel; import java.util.Scanner; /** * Ants * n只蚂蚁以每秒1cm的速度在长为Lcm的竿子上爬行,当蚂蚁爬到端点就会掉下去,竿 ...
- \r与\n
\n是换行,英文是New line \r是回车,英文是Carriage return
- Oracle性能优化之HINT的用法
1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_I ...
- Java overload和override的区别分析
Java overload和override的区别分析 方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现.重写(Overriding)是父类与子类之间多态性 ...