线程池应该设置多少线程合适,怎么样估算出来?其实之前对这块概念比较模糊(没怎么用到就渐渐忘了)。趁着项目要用到,仔细的研究了一遍,写下来作为笔记。
首先要明白一个概念:IO密集型和CPU密集型。
CPU密集型也叫计算密集型,这种类型大部分状况下,CPU使用时间远高于I/O耗时。有许多计算要处理、许多逻辑判断,几乎没有I/O操作的任务就属于CPU密集型。与之相反,IO密集型则是系统运行时,大部分时间都在进行I/O操作,CPU占用率不高。
如果是CPU密集型任务,频繁切换上下线程是不明智的,此时应该设置一个较小的线程数,比如CPU的数目加一。反之如果是IO密集型任务,应该尽可能的设置多线程,不让CPU闲下来(PS:但也不宜过多,需要注意线程切换的开销)。
综上我们可以明确,线程池设置线程数与CPU计算时间和I/O操作时间的比例相关,在此可以引出一个配置线程池大小的原则——阻抗匹配原则,其经验公式为:
C
考虑到P的值并不好评估,T的大小可以上下浮动50%。
这个公式原理也比较简单,T个线程,每个线程占用P的时间,正好可以占满C个CPU,也就是C = T * P。可以验证一下:
如果P = 1.0,C = 16,说明这是一个完全的密集计算,此时T = 16,也就是有几个CPU设置几个线程,这样能把CPU都利用起来。更多的线程也没用,因为CPU资源已经耗光。
如果P = 0.5,C = 16,说明每个线程只有50%的时间在使用CPU,此时T = 32,也就是32个50%繁忙的线程,能充分把CPU利用起来。
如果P < 0.2,这个公式就不适用了,因为线程不能无限开,会消耗大量资源。T可以取一个固定值,比如 8*C。
综上,CPU繁忙时间占比越高,设置线程数越少,CPU繁忙时间占比越低,设置线程数越多(当然也有限度)。
PS:在这使用多线程之前要确认一点,是否需要使用多线程,因为多线程会带来切换的开销,如果不断切换上下文的开销损耗和程序新增的复杂度大于并行带来的受益,那么是不建议使用多线程的。