从源码角度来分析线程池-ThreadPoolExecutor实现原理
- 降低了资源的消耗:通过池化技术,重复利用已创建好的线程。
- 增加了响应的速度:若有空闲线程时,直接执行任务,无需等待创建新的线程。
- 增加了系统的稳定性和可管理性:对系统而言,过多的线程会导致资源调度失衡,降低了系统的稳定性。线程池进行统一的管理(调优,监控和分配等),减少碎片化信息。
I. 线程池的类关系图

- Executor接口只有一个execute()方法,将任务的提交和运行进行解耦。
- ExecutorService接口在Executor的基础上,增加了生命周期的控制(线程池状态转换)和submit()方法生成Future结果。
- AbstractExecutorService是一个抽象类,实现了ExecutorService接口中的submit()方法,并实现了任务的执行流程。
- ThreadPoolExecutor主要实现两个功能:线程池生命周期管理,任务的执行execute()方法。
II. 生命周期管理
- workerCount: 表示线程池中有效的线程数量
- runState: 表示线程池当前的运行状态
ctl信息

COUNT_BITS=29(十进制)
CAPACITY=0000 1111 1111 1111 1111 1111 1111 1111(二进制)

信息获取:
int c = ctl.get();
workerCount = workerCountOf(c); //ctl的低28位表示线程数量
runState = runStateOf(c); //ctl的高四位表示状态
运行状态

- RUNNING: 可以接受新的任务请求,也可处理阻塞队列中的任务
- SHUTDOWN: 不接受新的任务请求,但会处理阻塞队列中的任务
- STOP: 不接受新的任务请求,阻塞队列也会直接清空,正在处理的任务也会被直接中断
- TIDYING: 所有的任务都已经终止,线程池中不存在有效线程
- TERMINATED: 线程池终止
III. 运行机制

- 任务请求
- 任务分配
- 添加worker
- 运行worker
- 任务拒绝
任务请求
- void execute(Runnable command):不需要获取任务结果。
- <T> Future<T> submit(Callable<T> task):需要获取任务结果。
任务分配
- 线程池线程数<核心线程数:创建一条新的线程,并在该线程上直接执行任务;
- 线程池线程数>=核心线程数 && 阻塞队列未满: 将任务推入阻塞队列中,并创建一条新的线程(若此时线程池存在有效线程则不创建),该线程获取阻塞队列头部的任务并执行;
- 线程池线程数>=核心线程数 && 阻塞队列已满 && 线程池线程数<最大线程数:创建一条新的线程,并在该线程直接执行任务;
- 线程池线程数>最大线程数 && 阻塞队列已满:任务拒绝。
添加worker
- firstTask:新创建线程执行的第一个任务,这里特指新提交的任务
- core:ture表示核心线程数,false表示最大线程数
运行worker
任务拒绝
获取任务结果
IV.实际案例
submit(Callable task)
public class MultiThreadPool {
private static List<String> hello = Arrays.asList("h", "e", "l", "l", "o");
private static String task(String args) {
System.out.println(String.format("submit - thread name: %s, args: %s", Thread.currentThread().getName(), args));
return args;
}
private static void submitTask() throws InterruptedException, ExecutionException, TimeoutException {
List<Future> futures = new ArrayList<>();
final ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 6, 10L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy());
try {
for (String str : hello) {
Thread.sleep(1);
Future f = executor.submit(() -> task(str));
futures.add(f);
}
for (Future f: futures) {
String result = (String) f.get(60, TimeUnit.SECONDS);
System.out.println(String.format("submit - thread name: %s, result: %s", Thread.currentThread().getName(), result));
}
} finally {
executor.shutdown();
}
}
public static void main(String[] args) throws Exception {
submitTask();
}
}
输出结果:
submit - thread name: pool-1-thread-3, args: l
submit - thread name: pool-1-thread-1, args: h
submit - thread name: pool-1-thread-4, args: l
submit - thread name: pool-1-thread-2, args: e
submit - thread name: pool-1-thread-3, args: o
submit - thread name: main, result: h
submit - thread name: main, result: e
submit - thread name: main, result: l
submit - thread name: main, result: l
submit - thread name: main, result: o
execute(Runnable task)
public class MultiThreadPool {
private static List<String> hello = Arrays.asList("h", "e", "l", "l", "o");
private static class Task implements Runnable {
private String arg;
Task(String arg) {
this.arg = arg;
}
public void run() {
System.out.println(String.format("execute - thread name: %s, args: %s", Thread.currentThread().getName(), arg));
}
}
private static void executeTask() throws InterruptedException, ExecutionException, TimeoutException {
Map<String, Future> futureMap = new HashMap<>();
final ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 6, 10L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy());
try {
for (String str : hello) {
Thread.sleep(1);
executor.execute(new Task(str));
}
} finally {
executor.shutdown();
}
}
public static void main(String[] args) throws Exception {
executeTask();
}
}
输出结果:
execute - thread name: pool-1-thread-3, args: l
execute - thread name: pool-1-thread-1, args: h
execute - thread name: pool-1-thread-4, args: l
execute - thread name: pool-1-thread-2, args: e
execute - thread name: pool-1-thread-3, args: o
从源码角度来分析线程池-ThreadPoolExecutor实现原理的更多相关文章
- Java并发包源码学习系列:线程池ThreadPoolExecutor源码解析
目录 ThreadPoolExecutor概述 线程池解决的优点 线程池处理流程 创建线程池 重要常量及字段 线程池的五种状态及转换 ThreadPoolExecutor构造参数及参数意义 Work类 ...
- Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析
目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...
- JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析
JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- Java8线程池ThreadPoolExecutor底层原理及其源码解析
小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...
- jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一)
jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一) 线程池介绍 在日常开发中经常会遇到需要使用其它线程将大量任务异步处理的场景(异步化以及提升系统的吞吐量),而在 ...
- 线程池ThreadPoolExecutor使用原理
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...
- 21.线程池ThreadPoolExecutor实现原理
1. 为什么要使用线程池 在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题.因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处: 降低资源消耗 ...
- 源码解读 TDengine 中线程池的实现
这篇文章中提到了 tsched 的源码可以一读,所以去阅读了一下,总共220来行. 1. 阅读前工作 通过上文了解到这段程序实现的是一个任务队列,同时带有线程池.这段程序是计算机操作系统里经典的con ...
随机推荐
- Oracle SQL Developer中查看解释计划Explain Plan的两种方法
方法一: 比如要查看解释计划的SQL是:select * from hy_emp 那么在输入窗口输入: EXPLAIN PLAN FOR select * from hy_emp 之后执行,输出窗口会 ...
- 用了这个jupyter插件,我已经半个月没打开过excel了
1 简介 jupyter lab是我迄今为止体验过开展数据分析等任务最舒适的平台,但这不代表它是完美的,因为在很多方面它仍然存在欠缺,譬如在对csv文件的交互式编辑方面. 图1 而本文将要介绍的jup ...
- 洛谷 P4072 [SDOI2016]征途 斜率优化DP
洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...
- appium多线程自动化
基于上篇讲述的appium自动启动停止.测试服务.对controller文件进行相应的修改 1.首先对start_server函数,应采用多线程模式启动多个server,如下 其中启动的每个线程函数s ...
- 在腾讯云云函数计算上部署.NET Core 3.1
云厂商(腾讯云.Azure等)提供了Serverless服务,借助于Serverless,开发人员可以更加专注于代码的开发,减少运维的成本.腾讯云的函数计算提供了很多运行库,对.NET的支持需要通过c ...
- (python)生产者消费者模型
生产者消费者模型当中有两大类重要的角色,一个是生产者(负责造数据的任务),另一个是消费者(接收造出来的数据进行进一步的操作). 为什么要使用生产者消费者模型? 在并发编程中,如果生产者处理速度很快,而 ...
- python之csrf简介
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防跨站请求伪造功能有分为全 ...
- virtualbox虚拟机之连接本地主机同时可以连接外部网络
如果主机需要通过ssh,ftp等方式访问linux虚拟机,是无法实现的.这个时候要实现端口互通,我们要用到VirtualBox的端口转发功能.所谓的端口转发功能,就是借助主机上虚拟出来的Virtual ...
- 必考算法之 Top K 问题
大家好,这里是<齐姐聊算法>系列之 Top K 问题. Top K 问题是面试中非常常考的算法题. 8 Leetcode 上这两题大同小异,这里以第一题为例. 题意: 给一组词,统计出现频 ...
- netty字节分包
高并发压测时,发现来自网关的消息出现粘包现象:分包就是势在必行的 前置和处理平台(暂时)使用netty通话,由于都是服务器平台使用DelimiterBasedFrameDecoder来解决分包 和网关 ...