I、UML
II、依赖
III、运行流程
IV、生命周期
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