转 根据CPU核心数肯定线程池并发线程数

转自: https://www.cnblogs.com/dennyzhangdd/p/6909771.html?utm_source=itdadao&utm_medium=referralhtml

 

 

正文算法

1、抛出问题

关于如何计算并发线程数,通常分两派,来自两本书,且都是好书,到底哪一个是对的?问题追踪后,整理以下:数据库

第一派:《Java Concurrency in Practice》即《java并发编程实践》,以下图:编程

 

如上图,在《Java Concurrency in Practice》一书中,给出了估算线程池大小的公式:swift

Nthreads=Ncpu*Ucpu*(1+w/c),其中服务器

Ncpu=CPU核心数网络

Ucpu=cpu使用率,0~1多线程

W/C=等待时间与计算时间的比率并发

 

第二派:《Programming Concurrency on the JVM Mastering》即《Java 虚拟机并发编程》

线程数=Ncpu/(1-阻塞系数)

2、分析

对于派系一,假设cpu100%运转,即撇开CPU使用率这个因素,线程数=Ncpu*(1+w/c)。

如今假设将派系二的公式等于派系一公式,即Ncpu/(1-阻塞系数)=Ncpu*(1+w/c),===》阻塞系数=w/(w+c),即阻塞系数=阻塞时间/(阻塞时间+计算时间),这个结论在派系二后续中获得应征,以下图:

因而可知,派系一和派系二实际上是一个公式......这样我就放心了......

 

3、实际应用

那么实际使用中并发线程数如何设置呢?分析以下(咱们以派系一公式为例):

Nthreads=Ncpu*(1+w/c)

IO密集型:通常状况下,若是存在IO,那么确定w/c>1(阻塞耗时通常都是计算耗时的不少倍),可是须要考虑系统内存有限(每开启一个线程都须要内存空间),这里须要上服务器测试具体多少个线程数适合(CPU占比、线程数、总耗时、内存消耗)。若是不想去测试,保守点取1即,Nthreads=Ncpu*(1+1)=2Ncpu。这样设置通常都OK。

计算密集型:假设没有等待w=0,则W/C=0. Nthreads=Ncpu。

至此结论就是:

IO密集型=2Ncpu(能够测试后本身控制大小,2Ncpu通常没问题)(常出现于线程中:数据库数据交互、文件上传下载、网络数据传输等等)

计算密集型=Ncpu(常出现于线程中:复杂算法)

java中:Ncpu=Runtime.getRuntime().availableProcessors()

=========================此处可略过=============================================

固然派系一种《Java Concurrency in Practice》还有一种说法,

即对于计算密集型的任务,在拥有N个处理器的系统上,当线程池的大小为N+1时,一般能实现最优的效率。(即便当计算密集型的线程偶尔因为缺失故障或者其余缘由而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费。)

即,计算密集型=Ncpu+1,可是这种作法致使的多一个cpu上下文切换是否值得,这里不考虑。读者可本身考量。

======================================================================

4、总结

选择线程池并发线程数的因素不少:任务类型、内存等线程中使用到全部资源都须要考虑。本文通过对现有文献的分析论证,得出结论,并给出了实际应用公式,实乃工程师之福利,技术之典范......

 

 

---

一针见血系列[2]: 线程池里面到底该设置多少个线程呢?论Java多线程和CPU核数的关系

转自: http://swiftlet.net/archives/3012

在Java中,经过下面的代码,咱们能够很容易地获取到系统可用的处理器核心数目:

基本原则是:应用程序的最小线程数应该等于可用的处理器核数。具体场景又分为如下两种状况:

(1)若是全部的任务都是计算密集型的,则建立处理器可用核心数那么多个线程就能够了。在这种状况下,建立更多的线程对程序性能而言反而是不利的。由于当有多个任务处于就绪状态时,处理器核心须要在线程间频繁进行上下文切换,而这种切换对程序性能损耗较大。
(2)若是任务都是IO密集型的,那么咱们就须要开更多的线程来提升性能。当一个任务执行IO操做时,其线程将被阻塞,因而处理器能够当即进行上下文切换以便处理其余就绪线程。若是咱们只有处理器可用核心数那么多个线程的话,即便有待执行的任务也没法处理,由于咱们已经拿不出更多的线程供处理器调度了。
总之,若是任务有50%的时间处于阻塞状态,则程序所需线程数为处理器可用核心数的两倍。若是任务被阻塞的时间少于50%,即这些任务是计算密集型的,则程序所需线程数将随之减小,但最少也不该低于处理器的核心数。若是任务被阻塞的时间大于执行时间,即该任务是IO密集型的,咱们就须要建立比处理器核心数大几倍数量的线程。计算出程序所需线程的总数的公式以下:

线程数=CPU可用核心数/(1-阻塞系数),其中阻塞系数的取值在0和1之间。

计算密集型任务的阻塞系数为0,而IO密集型任务的阻塞系数则接近1。一个彻底阻塞的任务是注定要挂掉的,因此咱们无须担忧阻塞系数会达到1。

相关文章
相关标签/搜索