Java线程池ThreadPoolExecutor的重要参数如何设置
前⾔:
最近业务上牵扯使⽤⼀个线程池,随时设置了⼏个参数,别⼈问了⼀句这个参数如何这样设置,由于我是随便设置的凭感觉经验吧,然
战狼2演员列表
后就想着找理论如何设置,爬楼⼤部分,分为两种⼀种是N*2确定核⼼数,这种感觉初始的线程核⼼数太⼩(io密集),没有⼀个感觉说服
我的,由于经验有限,⾃⼰选择了其中⼀种,⼤家要是有合适参考依据可以回复我,最合适的就是根据压测数据不断调整初始化线程池的参
数。
⼀、ThreadPoolExecutor的重要参数
1、corePoolSize:核⼼线程数
* 核⼼线程会⼀直存活,及时没有任务需要执⾏
形容优雅的成语
* 当线程数⼩于核⼼线程数时,即使有线程空闲,线程池也会优先创建新线程处理
* 设置allowCoreThreadTimeout=true(默认fal)时,核⼼线程会超时关闭
2、queueCapacity:任务队列容量(阻塞队列)
* 当核⼼线程数达到最⼤时,新任务会放在队列中排队等待执⾏
3、maxPoolSize:最⼤线程数
恢复强制执行申请书* 当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务
* 当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务⽽抛出异常
4、 keepAliveTime:线程空闲时间
* 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
* 如果allowCoreThreadTimeout=true,则会直到线程数量=0
5、allowCoreThreadTimeout:允许核⼼线程超时
6、rejectedExecutionHandler:任务拒绝处理器
* 两种情况会拒绝处理任务:
- 当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务
- 当线程池被调⽤shutdown()后,会等待线程池⾥的任务执⾏完毕,再shutdown。如果在调⽤shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务 * 线程池会调⽤rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常
* ThreadPoolExecutor类有⼏个内部实现类来处理这类情况:
- AbortPolicy 丢弃任务,抛运⾏时异常
- CallerRunsPolicy 执⾏任务
- DiscardPolicy 忽视,什么都不会发⽣
- DiscardOldestPolicy 从队列中踢出最先进⼊队列(最后⼀个执⾏)的任务
* 实现RejectedExecutionHandler接⼝,可⾃定义处理器监管账户
⼆、ThreadPoolExecutor执⾏顺序
线程池按以下⾏为执⾏任务
1. 当线程数⼩于核⼼线程数时,创建线程。
2. 当线程数⼤于等于核⼼线程数,且任务队列未满时,将任务放⼊任务队列。
3. 当线程数⼤于等于核⼼线程数,且任务队列已满
- 若线程数⼩于最⼤线程数,创建线程
- 若线程数等于最⼤线程数,抛出异常,拒绝任务
微信扫雷
三、如何设置参数
1、默认值
* corePoolSize=1
* queueCapacity=Integer.MAX_VALUE
tp网址
* maxPoolSize=Integer.MAX_VALUE
* keepAliveTime=60s
* allowCoreThreadTimeout=fal
* rejectedExecutionHandler=AbortPolicy()
2、如何来设置
* 需要根据⼏个值来决定
- tasks :每秒的任务数,假设为500~1000
- taskcost:每个任务花费时间,假设为0.1s
- respontime:系统允许容忍的最⼤响应时间,假设为1s
* 做⼏个计算
- corePoolSize = 每秒需要多少个线程处理?
* threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 个线程。corePoolSize设置应该⼤于50提高警惕保卫祖国
* 根据8020原则,如果80%的每秒任务数⼩于800,那么corePoolSize设置为80即可
什么人不用电- queueCapacity = (coreSizePool/taskcost)*respontime
* 计算可得 queueCapacity = 80/0.1*1 = 800。意思是队列⾥的线程可以等待1s,超过了的需要新开线程来执⾏
* 切记不能设置为Integer.MAX_VALUE,这样队列会很⼤,线程数只会保持在corePoolSize⼤⼩,当任务陡增时,不能新开线程来执⾏,响应时间会随之陡增 - maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)
*⽹上⼤部分都是这样的代码,这样最⼤容量就会⼩于核⼼,肯定有问题,为什么⽹上这么传我也很疑问有⼈知道的话可以指教下,所以我觉得这 * 计算可得 maxPoolSize = (1000-800)/10 = 20
* (最⼤任务数-队列容量)/每个线程每秒处理能⼒ = 最⼤线程数
- rejectedExecutionHandler:根据具体情况来决定,任务不重要可丢弃,任务重要则要利⽤⼀些缓冲机制来处理
- keepAliveTime和allowCoreThreadTimeout采⽤默认通常能满⾜
3、以上都是理想值,实际情况下要根据机器性能来决定。如果在未达到最⼤线程数的情况机器cpu load已经满了,则需要通过升级硬件(呵呵)和优化代码,降低
四 有什么好的凭证指教下
⽬前我使⽤⽅案是根据上⾯算出了核⼼的线程数corePoolSize,然后maxPoolSize和它相等,队列⼤⼩为上⾯公式计算