从源码角度来分析线程池-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 ...
随机推荐
- 异步(async)编程
思考:为什么要使用异步编程? 我们先看看同步方法和异步方法之前在程序中执行的逻辑: 1. 同步方法 static void Main(string[] args) { Console.WriteLin ...
- JavaScript函数及面向对象
函数及面向对象 目录 函数及面向对象 1. 定义函数 1. 定义方式一 2. 定义方式二 2. 调用函数 1. 参数问题 2. arguments 3. rest 3. 变量的作用域 1 . var的 ...
- 阿里云短信服务验证码封装类 - PHP
本文记录在ThinkPHP6.0中使用阿里云短信验证码,该封装类不仅仅局限于TP,拿来即用 使用该类之前必须引入 flc/dysms 扩展,该封装类就是基于这个扩展写的 composer requir ...
- pycharm之ctrl+鼠标滚轮调整字体大小
按照图示设置,可以添加:ctrl+鼠标滚轮调整字体大小功能 1. 2.
- 利用 QEMU USER 模式运行 mips 程序
摘要 关键字: qemu mips 前述 QEMU是一个处理器模拟软件,可以用来在PC中模拟ARM.MIPS等多种架构的软硬件运行环境.QEMU主要有两种模拟模式: User Mode System模 ...
- [CF571B]Minimization(贪心+DP)
题目链接 http://codeforces.com/problemset/problem/571/B 题意 给数组,得到公式最小值. 题解 由题分成的子数组只有两种长度,每种长度的数组数量也是固定的 ...
- command三国杀开发日记20200914
目前状态 一时脑热开始写的东西,计划完全使用C语言实现,尽量使用通用接口,能够在windows上直接运行 几乎是一穷二白,初步搭建了牌堆.玩家信息接口体,编写了简单的UI函数,能够将玩家信息显示在屏幕 ...
- 分布式系统监视zabbix讲解九之使用snmp监控windows
zabbix监控windows演示 第一步:开启服务. 控制面板>程序>程序和功能>打开或关闭windows功能,勾选上简单网络管理协议(SNMP),以及下面的子程序.点击确定 第二 ...
- Python爬虫和函数调试
一:函数调试 用之前学过的try···except进行调试 def gameover(setA,setB): if setA==3 or setB==3: return True else: retu ...
- RabbitMQ Server安装及显示管理界面Installing on Windows
接上一篇文章,继续讲解 文件很小, 1.下载路径:http://www.rabbitmq.com/download.html 2.运行rabbitmq-server-3.6.5.exe,选择要安装的目 ...