I、UML
文章图片
II、依赖
文章图片
III、运行流程
文章图片
IV、生命周期
【api-java.util.concurrent.ThreadPoolExecutor】
文章图片
run state | desc |
---|---|
RUNNING | 能接收新任务,且能处理队列中任务 |
SHUTDOWN | 不能接收新任务,但能继续处理队列中任务 |
STOP | 新任务和队列中任务都不能处理,会中断正在处理任务的线程 |
TIDYING | 所有任务已终止 |
TERMINATED | terminated()之后的状态 |
文章图片
V、任务调度 1、首先检测线程池运行状态,如果不是RUNNING,则直接拒绝,线程池要保证在RUNNING的状态下执行任务。
2、如果workerCount < corePoolSize,则创建并启动一个线程来执行新提交的任务。
3、如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中。
4、如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务。
5、如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。
文章图片
VI、Worker
文章图片
1、任务是 Runnable(内部变量名叫 task 或 command),线程是 Worker。
2、Worker持有一个线程thread
3、Worker是通过继承AQS,使用AQS来实现独占锁这个功能。没有使用可重入锁ReentrantLock,而是使用AQS,为的就是实现不可重入的特性去反应线程现在的执行状态。
——lock方法一旦获取了独占锁,表示当前线程正在执行任务中。
——如果正在执行任务,则不应该中断线程。
——如果该线程现在不是独占锁的状态,也就是空闲的状态,说明它没有在处理任务,这时可以对该线程进行中断。
——线程池在执行shutdown方法或tryTerminate方法时会调用interruptIdleWorkers方法来中断空闲的线程,interruptIdleWorkers方法会使用tryLock方法来判断线程池中的线程是否是空闲状态;如果线程是空闲状态则可以安全回收。
4、执行任务流程
文章图片
VII、需要关注和验证的几个重要知识点
1、线程池初始化线程数是可动态调整的。调小时任务将重新进入for循环。验证调大和调小时任务是否有影响。
2、线程池一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。创建销毁线程的开销、调度线程的开销。怎么验证这两种开销???
3、设置的线程数过多可能还会引发线程上下文切换频繁的问题,也会降低处理任务的速度,降低吞吐量???还是怎么验证开销???
4、最大核心数设置偏小,大量抛出RejectedExecutionException,触发接口降级条件。就是说是一种动态降级的方案。
5、队列设置过长,最大线程数设置失效,导致请求数量增加时,大量任务堆积在队列中,任务执行时间过长。嵌套的线程池,会不会出现第一层的任务正在执行,与之关联的第二层任务正在等待,从而导致响应时间长???
VIII、参考文章:
https://www.javadoop.com/post/java-thread-pool
https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)