如何确定线程池中指定多少线程合适?
线程池确实可以减少线程创建和销毁的开销,提高效率,可以复用线程。但是一个线程池中应该指定多少线程合适呢?指定多少核心线程,最大线程数设置为多少合适呢?
其实具体的线程数量需要根据不同的服务器和不同的使用场景确定的,脱离了场景去说线程池指定多少线程合适是没有意义的。
1. 常见场景
一般情况下,我们的实际场景跳不出这个三个场景:
1. IO密集型
线程池中的大多数任务都是执行IO操作的。IO操作时需要比较长时间的等待的,对于CPU的利用率并不高。所以这时候可以适当的多指定一些线程,当某个线程IO阻塞的时候,让其他线程执行运算操作。
一般IO密集型可以将线程数设置为 CPU核心数 * 2
,用来提高CPU的利用率。
个人感觉这个值其实是有些保守的
CPU核心数或CPU并行处理的线程数(注意:这里说的是并行)在Java中可以使用 Runtime.getRuntime().availableProcessors()
命令获取到。
2. CPU密集型
这类任务主要是需要执行计算操作的,响应速度会很快,这种类型的任务CPU的利用率比较高。
如果是CPU密集型的操作的话,保证每个线程的正常运作应该是效率最高的。因为如果线程数很多的话, CPU可能需要频繁的切换线程的上下文,在切换的时候,对于CPU的运算速度也是有损耗的。
所以如果是CPU密集型的话,推荐线程个数与CPU核心数或CPU能并行处理线程数相同(注意:这里说的是并行)
3. 混合型任务
此类任务既需要使用CPU进行运算,有需要执行IO操作,比较常见就是Web服务器的HTTP请求处理操作。
这类任务中,在任务中的CPU的运行时间相对来说占用的时间是比较少的,而IO操作的时间占用的时间是相对较长的。
针对这种任务,书中说业界有一个相对成熟的公式用来计算比较合适的线程数:
(
线
程
等
待
时
间
+
线
程
C
P
U
时
间
)
/
线
程
C
P
U
时
间
∗
C
P
U
核
心
数
(线程等待时间 + 线程CPU时间) / 线程CPU时间 * CPU核心数
(线程等待时间+线程CPU时间)/线程CPU时间∗CPU核心数
例如,假设线程CPU使用时间占用 100ms,等待时间占用500ms,CPU核心数为 4,则可以得到:
(
500
+
100
)
/
100
∗
4
=
24
(500 + 100) / 100 * 4 = 24
(500+100)/100∗4=24
可以计算出大概使用24个线程比较合适。
当然这个只是一个估算值,还要参考具体的使用环境,硬件性能,硬盘读写速度等因素,具体使用的时候,还是需要具体的进行调试,调试到一个比较合适的值。
这里个人有个小疑惑, 为什么混合型可以这样计算,IO型不能这么计算?是因为IO型使用时间不确定吗?IO密集型的操作,使用CPU核心数 * 2 这个值,是不是有些保守了呢?
有知道的大哥还希望可以解惑一二,在此谢过了。