问一下,线程池里面到底该设置多少个线程?

小哈学Java

共 1557字,需浏览 4分钟

 · 2020-07-14


点击上方蓝色“小哈学Java”,选择“设为星标

回复“资源”获取独家整理的学习资料!

1c0b7771f18e8c48e7bf64964acf57f5.webp

328b2db192517e7396c3d7d28c5ddc49.webp

作者 | 只会一点java

来源 | cnblogs.com/dennyzhangdd/p/6909771.html

一、抛出问题

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

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

b4d7405471131f7736ff5bda2f1a9abf.webp

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

Nthreads=NcpuUcpu(1+w/c),其中

Ncpu=CPU核心数

Ucpu=cpu使用率,0~1

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

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

ea69c432ae1181c850e9ffeff90c6171.webp

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

二、分析

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

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

148e430bc18d555b90ecb714c140f90a.webp

由此可见,派系一和派系二其实是一个公式……这样我就放心了……

三、实际应用

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

Nthreads=Ncpu*(1+w/c)

IO密集型:一般情况下,如果存在IO,那么肯定w/c>1(阻塞耗时一般都是计算耗时的很多倍),但是需要考虑系统内存有限(每开启一个线程都需要内存空间),这里需要上服务器测试具体多少个线程数适合(CPU占比、线程数、总耗时、内存消耗)。如果不想去测试,保守点取1即,Nthreads=Ncpu*(1+1)=2Ncpu。这样设置一般都OK。扩展一下:JAVA多线程和并发基础面试问答

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

至此结论就是:

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

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

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

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

864b32cc907264b1613b393dbc2cd484.webp

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

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

四、总结:

选择线程池并发线程数的因素很多:任务类型、内存等线程中使用到所有资源都需要考虑。

END


2f07fc7d912a7fb3ae2f10949deb55bd.webp

有热门推荐?

1. 序列化:ProtoBuf与JSON的比较

2. SQL 查找是否"存在",别再 count 了,很耗费时间的!

3. 实战:使用Nginx限流

4. 给 Spring Boot 项目减减肥!18.18M 到 0.18M 是如何做到的?

最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

浏览 5
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报