最佳线程数
这些天也是遇到一个问题,如何为线程池选择和是的最佳线程数?
相信大家都有在使用线程池时,很多同学都有这样的疑问,不知道如何配置线程数量,今天我们一起探讨一下这个问题。
首先在配置线程数量之前,要看任务的类型是 IO密集型,还是CPU密集型?
那么什么是IO密集型什么又是CPU密集型呢?
CPU 密集型
CPU密集型也叫计算机密集型,指的是系统的硬盘、内存性能相对的比CPU要好很多,此时系统中运作的大部分状况还是CPU100%,CPU要进行读写IO,IO在很短的时间就可以完成,而CPU还有许多运算要处理,所以CPU的Loading很高
在多重程序系统中,大部分时间用来做计算、逻辑判断等CPU动作的程序成为CPU密集型,指非常复杂的调用,循环次数很多,或者递归调用层次很深等。例如:一个计算圆周率小数点后一千位以下的程序,在执行的过程中大部分时间用于计算三角函数和开根号这便是属于CPU密集型的程序。
IO密集型
IO密集型指的是系统的CPU性能相对于硬盘、内存要好很多,此时系统运作,大部分的状况是CPU在等待IO的读写操作,CPU的Loading并不高
处理方式
IO密集型配置线程数经验值是:2N,其中N代表CPU核数。
CPU密集型配置线程数经验值是:N + 1,其中N代表CPU核数。
但是在实际的开发中,并不会按照上面的公式进行设置,那么我们又是有什么样的方法给线程池设置一个合适的线程数呢?
对于IO密集型的在网上还有另一个公式:线程数=CPU核心数/(1-阻塞系数)
引入和阻塞系数的说法,一般为0.8~0.9之间
还有另一种
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
因为很显然,线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
而在我们的实际业务中使用的基本都是IO密集型,因为往往我们都是对数据库操作,访问redis,es等存储型组件,涉及到的也就是磁盘IO和网络IO
那么什么时候是CPU密集型,一般的纯计算的都属于CPU密集型
经验:一般IO密集型,可以考虑多一些线程,主要目的是为了增加IO的并发度,而CPU密集型不宜设置过多的线程,因为线程切换,反而造成性能损耗
那么我们怎样判断需要增加更多的线程呢
其实我们可以使用jstack
命令查看一下进程的线程栈,如果实践过程中发现了线程池中的大量线程都处于等待状态,则说明线程够用。如果大部分线程都处于运行状态,那么可以适当的调高线程数量
如果采用阻塞系数的方式,发现数据库的操作耗时比较多,此时可以继续提高阻塞系数,从而增大线程数量