前言
在实际开发中,业务场景是多种多样的,分为IO密集型与CPU密集型俩种。针对不同的场景。如何配置一个合理的线程池是十分重要的~。
接下来我从Java线程池的生命周期以及实际开发场景讲解如何配置Java线程池
Java线程池
线程池七大参数
- 核心线程数
- 最大线程数
- 线程空闲保持时间
- 时间单位
- 等待队列(存放待执行的队列):
- 线程创建工厂
- 拒绝策略
等待队列分有界与无界俩种
有界:有长度,会触发拒绝策略
无界:无限添加
一般实际开发中都是用有界的。避免历史线程造成服务的不可用
Java线程池创建线程的生命周期
Java线程池中线程是在使用时创建的,并非在线程池创建时
- 当并发线程数< 核心线程数时:创建核心线程
- 核心线程已满时:新线程进入等待队列
- 等待队列已满时:创建最大线程数
- 当等待队列已满&&达到最大线程数时:新线程进入触发拒绝策略
- 当最大线程数空闲超过空闲保持时间时:线程销毁(非核心线程)===>. 作用:避免线程数过多造成线程切换的消耗
Java线程池的拒绝策略
- 抛出异常
- 由调用线程执行(串型,不走多线程)
- 直接丢弃
- 丢弃最早未处理任务(LRU)
实际开发配置
对Java线程池有了了解后,就可以针对不同的场景去配置线程池了
IO密集型
解释
IO密集型是指内存传输操作较多,CPU有大量时间处于等待IO的状态下。
这个时候需要增大线程数,配置更多的线程来充分利用CPU。
实际配置
- 核心线程数:通常是CPU核数的2~4倍。根据实际IO等待时间而定
- 最大线程数:通常是核心线程数的2倍
- 队列:有界队列,长度可以大一点. 可以配在100左右(根据核数定)
- 拒绝策略:拒绝策略一般按需求定. 常用的是:抛出异常 或者 由调用线程执行
- 最大空闲时间:一般是30~60s,根据qps是否平均而定
CPU密集型
解释
CPU密集型任务是指计算操作较多,CPU资源是瓶颈。
因此线程数不宜过多,以避免过度上下文切换。
实际配置
- 核心线程数:CPU核数+1。略多于CPU核数即可
- 最大线程数:核心线程数+1。略多于核心线程数即可
- 队列:有界队列,长度不用过大. 可以配置在50左右
- 拒绝策略:拒绝策略一般按需求定. 常用的是:抛出异常 或者 由调用线程执行
- 最大空闲时间:一般是30~60s,根据qps是否平均而定
总结
IO密集型任务:配置更多线程(通常是CPU核心数的2到4倍),以充分利用CPU资源。
CPU密集型任务:配置接近于CPU核心数的线程数,以避免过度上下文切换。
思考
知道单机QPS怎么配置线程池?
- 先计算并发线程数:并发线程数= QPS * T(平响)
- 判断场景类型:IO密集型 or CPU密集型
- IO密集型:
- 核心线程数:并发线程数
- 最大线程数:核心线程数 * 2
- CPU密集型:
- 核心线程数:CPU核数+1
- 最大线程数:略多于核心线程数
- IO密集型: