https://blog.csdn.net/xiang__liu/article/details/82796543
1. 线程池配置规则: 线程池大小=CPU个数 * CPU期望利用率 * (1 + 任务等待时间 / 任务处理时间)
线程池的理想大小取决于被提交任务的类型以及所部署系统的特性。线程池应该避免设置的过大或过小,如果线程池过大,大量的线程将在相对很少的CPU和内存资源上发生竞争,这不仅会导致更高的内存使用量,而且还可能耗尽资源。如果线程池过小,那么将导致许多空闲处理器无法执行任务,降低了系统吞吐率。
要正确设置线程池的大小,必须分析计算环境、资源预算和任务特性。包括所部署系统的CPU个数、内存大小、任务类型(计算密集、IO密集等)。如果待处理任务行为特征差异较大,那应该考虑使用多个线程池,分别处理不同类任务。大致上来说,对于计算密集型任务线程池大小和CPU个数相近通常能实现最优利用率;对于IO密集型任务,由于线程不会一直执行,所以线程吃的规模应该更大。要正确设置线程池大小,需要估算出任务的等待时间(任务从提交到结束耗时)和处理时间(实际处理耗时)的比值。
要是处理器达到期望的使用率,线程池的最优大小等于:
线程池大小=CPU个数 * CPU期望利用率 * (1 + 任务等待时间 / 任务处理时间)
假设有一个定时解析大文件并存入数据库的任务,系统部署在8核服务器上,期望定时任务执行CPU占比约20%,任务平均等待时间为150ms,任务平均处理时间为50ms
线程池最优大小=8*0.2*(1+150/50)=3
三、如何设置参数
默认值
corePoolSize=1
queueCapacity=Integer.MAX_VALUE
maxPoolSize=Integer.MAX_VALUE
keepAliveTime=60s
allowCoreThreadTimeout=false
rejectedExecutionHandler=AbortPolicy()
如何来设置
需要根据几个值来决定
tasks :每秒的任务数,假设为500~1000
taskcost:每个任务花费时间,假设为0.1s
responsetime:系统允许容忍的最大响应时间,假设为1s
做几个计算
corePoolSize = 每秒需要多少个线程处理?
threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 个线程。corePoolSize设置应该大于50
根据8020原则,如果80%的每秒任务数小于800,那么corePoolSize设置为80即可
queueCapacity = (coreSizePool/taskcost)*responsetime
计算可得 queueCapacity = 80/0.1*1 = 80。意思是队列里的线程可以等待1s,超过了的需要新开线程来执行
切记不能设置为Integer.MAX_VALUE,这样队列会很大,线程数只会保持在corePoolSize大小,当任务陡增时,不能新开线程来执行,响应时间会随之陡增。
maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)
计算可得 maxPoolSize = (1000-80)/10 = 92
(最大任务数-队列容量)/每个线程每秒处理能力 = 最大线程数
rejectedExecutionHandler:根据具体情况来决定,任务不重要可丢弃,任务重要则要利用一些缓冲机制来处理
keepAliveTime和allowCoreThreadTimeout采用默认通常能满足
以上都是理想值,实际情况下要根据机器性能来决定。如果在未达到最大线程数的情况机器cpu load已经满了,则需要通过升级硬件(呵呵)和优化代码,降低taskcost来处理。
网友评论