spring中使用ThreadPoolTaskExecutor配置线程池

背景

spring中经常使用ThreadPoolTaskExecutor来调用JDK的ThreadPoolExecutor初始化线程池, 尤其在有异步执行的任务时, 由于spring 异步任务默认使用的executor不会reuse线程, 因此需要设置默认线程池, 来替换spring 默认的SimpleAsyncTaskExecutor

spring中使用ThreadPoolTaskExecutor配置线程池_第1张图片

参数

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

写在最后

但是软件工程实践没有银弹 , 一切都要结合实际场景去考虑

你可能感兴趣的:(java,spring,java)