【线程池】如何正确设置线程池的线程数,提高性能

本文介绍了如何根据CPU密集型和IO密集型任务来设置线程池的线程数,以优化性能。建议CPU密集型设置为N+1,IO密集型设置为2N,同时考虑业务逻辑复杂度和等待时间占比。在实际应用中,还需要关注数据库连接数限制,避免影响其他服务性能。此外,线程池配置需注意内部线程池的大小,确保预期效果。压力测试是确定合适线程数的重要手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

往往在生产环境中,工作线程数,设置小了,无法充分利用CPU资源,性能会下降。设置大,线程上下文切换过于频繁,反而会使性能降低。

可以关注一下协程,如java库提供的Quasar fiber轻量级线程、kilim以及kotlin语言支持的协程。java线程是用户线程与内核线程之间映射的,1:1模式,是通过内核完成调度的。而协程是N个内核线程多路复用M个协程的,N:M的模式,也就是在用户态的协程调度器完成的,减少了与内核之前的交互。可以很好的避免上下文切换。

如何设置线程池的线程数

首先我们先理解多线程执行的类型分为CPU密集型和IO密集型两种:

  • CPU密集型,程序计算相关的(如定价里的规则引擎计算逻辑可以视为CPU密集型),消耗CPU资源,线程数可以小点。
  • IO密集型,网络、磁盘IO操作,如访问数据库,RPC调用,缓存之类的,这部分都会存在等待时间,不占用CPU,我们可以设置大点,充分利用CPU资源。

在这里插入图片描述

1)从工作队列里拿出任务,本地会做一下参数封装
2)访问cache拿一些数据
3)拿到cache里的数据后,再进行一些业务逻辑相关
4)通过RPC调用下游service再拿一些数据
5)RPC调用结束后,再进行业务逻辑相关
6)访问DB进行一些数据操作
7)操作完数据库之后做一些收尾工作,在进行业务逻辑相关。

分析整个流程图:

  • 1)其中1,3,5,7步骤中,线程进行本地业务逻辑计算时需要占用CPU资源,假设计算执行时间是100ms
  • 2)而2,4,6步骤中,访问cache、service、DB过程中线程处于一个等待结果的状态,不需要占用CPU,假设等待时间也是100ms

得到的结论:假设此时是单核,则设置为2个工作线程就可以把CPU充分利用起来,让CPU跑到100% ;假设此时是N核,则设置为2N个工作现场就可以把CPU充分利用起来,让CPU跑到N*100%。

如果业务不是很复杂,CPU密集型可以设置为N+1,IO密集型设置2N的线程数(Netty源码也是默认用的这个公式)。如果业务涉及很多业务逻辑,可以使用:线程数=N(CPU核数)*(1+(线程等待时间)/(线程时间运行时间))

但是在设置合理的线程数之前,我们还得需要考虑一下DB的连接数,以及其他RPC服务的承载能力,别自己服务性能提升了几倍,影响到其他服务性能。比如云库默认连接池是2000,我们总共60机器,单台机器设置的线程数是40,那么打到DB上的请求是40X60=2400,那么DB拒绝连接了。

意思考虑数据库的支持上限,尽量让(线程数*机器数)<2000

还有一个注意点:举例clover,它本身就是存在线程池的,然后我们业务逻辑又初始化线程池达到异步效果(线程池共享的)。如clover设置了10个,但是内部线程池设置了10或者是小于10,这样往往达不到你预期的效果,你可以把内部的线程池调大点,或者是去掉内部线程池。这个之前compleableFuture也强调了这点。

3. 总结

  • 如果业务不是很复杂,CPU密集型可以设置为N+1,IO密集型设置2N的线程数(Netty源码也是默认用的这个公式)。

  • 如果业务涉及很多业务逻辑,可以使用:线程数=N(CPU核数)*(1+(线程等待时间)/(线程时间运行时间))

    这个除法公式的核心思想是等待时间占比越大,线程数就越大,尽量让多个线程去抢占运算资源,否则线程都IO阻塞了,浪费资源。也就是说2n+1公式是经验值,io约占66%时间,cpu约占33%时间,如果io增加到75%,那么线程数就等于3n+1,如果io增加到80%,线程数就等于4n+1。

3.1 怎么计算IO与cpu时间占比呢?

  • 耗时短,理论上只能估算,因为几十甚至十几毫秒,不好通过日志打印。

  • 耗时特别多的业务,通过日志计算时间。

最准确的办法,就是压力测试,查看队列是否会满。


参考:
《如何正确设置线程池的线程数,提高性能》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值