1.线程池和CPU核心数的关系
- 一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU processors的个数)
(1)如果是CPU密集型应用,则线程池大小设置为N+1(或者是N),线程的应用场景:主要是复杂算法
(2)如果是IO密集型应用,则线程池大小设置为2N+1(或者是2N),线程的应用场景:主要是:数据库数据的交互,文件上传下载,网络数据传输等等
+1的原因是:即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费。 - 如果一台服务器上只部署这一个应用并且只有这一个线程池,那么这种估算或许合理,具体还需自行测试验证。
但是,IO优化中,这样的估算公式可能更适合:
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目。
因为很显然:
(1)线程等待时间所占比例越高,需要越多线程。
(2)线程CPU时间所占比例越高,需要越少线程。
eg:
比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,
那么根据上面这个公式估算得到:
((0.5+1.5)/0.5)*8=32。
这个公式进一步转化为:最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目。
刚刚说到的线程池大小的经验值,其实是这种公式的一种估算值。
2.常见概念:CPU的核心数,CPU的线程数
- CPU的核心数:
CPU的核心数是指物理上,也就是硬件上存在着几个核心。
比如,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组 - CPU的线程数:
对于一个CPU,线程数总是大于或等于核心数的。
(1)一个核心最少对应一个线程,但通过超线程技术,一个核心可以对应两个线程,也就是说它可以同时运行两个线程。
(2)CPU之所以要增加线程数,是源于多任务处理的需要。线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。 - eg:
在Windows中,在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”即可查看物理CPU数、CPU核心数、线程数。
其中:
Name:表示物理CPU数
NumberOfCores:表示CPU核心数
NumberOfLogicalProcessors:表示CPU线程数
(1)CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的
(2)如果没有超线程技术,一个CPU核心对应一个线程。 所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。
3.是否使用线程池就一定比使用单线程高效呢?
-
答案是否定的,比如Redis就是单线程的,但它却非常高效,基本操作都能达到十万量级/s。从线程这个角度来看,部分原因在于:
(1)多线程带来线程上下文切换开销,单线程就没有这种开销
(2)锁 -
当然“Redis很快”更本质的原因在于:
Redis基本都是内存操作,这种情况下单线程可以很高效地利用CPU。而多线程适用场景一般是:存在相当比例的IO和网络操作。 -
所以即使有上面的简单估算方法,也许看似合理,但实际上也未必合理,都需要结合系统真实情况(比如是IO密集型或者是CPU密集型或者是纯内存操作)和硬件环境(CPU、内存、硬盘读写速度、网络状况等)来不断尝试达到一个符合实际的合理估算值。
参考:
线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事
https://blog.csdn.net/bsfz_2018/article/details/80105138
ava线程池大小为何会大多被设置成CPU核心数+1?
https://www.zhihu.com/question/38128980
如何合理地估算线程池大小?
http://ifeve.com/how-to-calculate-threadpool-size/
深入理解-CPU核心数与线程池并发线程数关系
https://www.lagou.com/lgeduarticle/58961.html
根据CPU核心数确定线程池并发线程数
https://www.cnblogs.com/dennyzhangdd/p/6909771.html?utm_source=itdadao&utm_medium=referral