文章目录

  • ​​1.线程池和CPU核心数的关系​​
  • ​​2.常见概念:CPU的核心数,CPU的线程数​​
  • ​​3.是否使用线程池就一定比使用单线程高效呢?​​

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的核心数、线程数的关系和区别,同步与堵塞完全是两码事


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核心数确定线程池并发线程数