背景
spring中经常使用ThreadPoolTaskExecutor
来调用JDK的ThreadPoolExecutor初始化线程池, 尤其在有异步执行的任务时, 由于spring 异步任务默认使用的executor不会reuse线程
, 因此需要设置默认线程池, 来替换
spring 默认的SimpleAsyncTaskExecutor
参数
ThreadPoolTaskExecutor 不同的参数设置会使executor采用不同的策略
-
CorePoolSize 核心线程数
默认值为1
, 默认不会空闲销毁的线程, 可以设置AllowCoreThreadTimeOut=true(默认为false)
来控制
核心线程空闲回收
-
MaxPoolSize 最大线程数
线程池能容纳的
最大
线程数 -
QueueCapacity 线程池队列容量
只有当队列容量满了, 才会创建新的线程执行任务, 否则放在队列中等待, 并且
等待核心线程处理任务
-
RejectedExecutionHandler 当线程池达到max size时, 执行的策略
如果线程池满了, 再进来新的任务, 将会执行rejected策略
改变上述参数值, 线程池分别表现为以下策略:
if 「线程池中线程的数量」<
「corePoolSize 」:
创建新的线程来处理任务, 即便线程池中其他线程都是空闲状态
else if 「线程池中线程的数量」==
「corePoolSize 」
&&
「QueueCapacity」未满 :
任务将被放入队列中等待线程执行
else if 「线程池中线程的数量」>
「corePoolSize 」
&&
「QueueCapacity」已满
&&
「线程池中线程的数量」<
「MaxPoolSize」:
创建新的线程来处理任务
else if 「线程池中线程的数量」<
「corePoolSize 」
&&
「QueueCapacity」已满
&&
「线程池中线程的数量」==
「MaxPoolSize」:
通过制定rejectedHandler处理
综上, 线程池执行的顺序即:
- 核心线程corePoolSize?
- 任务队列workQueue?
- 最大线程 maximumPoolSize?
- 如果三者都满了,使用handler处理被拒绝的任务
另外 如果线程池中的线程数 >
「corePoolSize」, 并且超过了『keepAliveTime(默认为60s)』, 线程将被回收, 以此来达到动态管理
线程池的线程数
如何设置这些值
因为要考虑:
- 运行机器的
硬件参数
- 期望的CPU占用率
- 不同
应用程序类型
(IO密集型/CPU密集型) - 业务场景是否特别要求性能
种种情况, 组合的case就非常多了, 推荐的设置值是:
-
corePoolSize = CPU线程数/2
Runtime.getRuntime().availableProcessors()//获取逻辑核心数,如6核心12线程,那么返回的是12
-
maxPoolSize = CPU 线程数
-
queueCapacity = ( corePoolSize / 任务处理时间 ) * 期望等待时间(秒)
-
rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy() 如果线程池满了, 丢给caller线程执行
有兴趣参考:
https://juejin.cn/post/6948034657321484318文章来源:https://www.toymoban.com/news/detail-427857.html
写在最后
但是软件工程实践没有银弹
, 一切都要结合实际场景去考虑文章来源地址https://www.toymoban.com/news/detail-427857.html
到了这里,关于spring中使用ThreadPoolTaskExecutor配置线程池的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!