多线程 - 如何合理配置线程池
总结
根据“任务的性质”分析
CPU 密集型任务
- 和内存打交道,大量计算。例如大数的计算,正则匹配
- 如何配置:
- CPU 密集型任务应配置尽可能小的线程,如配置 Ncpu+1 个线程的线程池(Ncpu 是处理器的核的数目),这样留一个空出来,用来做切换。。
- 如果线程太多,会造成线程在CPU内部的上下文切换。。CPU的线程上下文切换比指令执行耗时的更多。
IO 密集型任务
- 解释:和磁盘,网络,文件,数据库交互很多的。
- 如何配置:由于 IO 密集型任务线程并不是一直在执行任务,在操作的时间,是不消耗CPU的。不会经常在CPU内切换线程上下文,则应配置尽可能多的线程,如 2*Ncpu。
-
对于 IO 型的任务的最佳线程数,有个公式可以计算 Nthreads = NCPU * UCPU * (1 + W/C)
❑NCPU 是处理器的核的数目❑UCPU 是期望的 CPU 利用率(该值应该介于 0 和 1 之间)
❑W/C 是等待时间与计算时间的比率。等待时间与计算时间我们在 Linux 下使用相关的 vmstat 命令或者 top 命令查看。
-
混合型任务
- 解释:前两者的混合
- 如何配置:如果可以拆分,将其拆分成一个 CPU 密集型任务和一个 IO 密集型任务。
- 只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐 量将高于串行执行的吞吐量。
- 如果这两个任务执行时间相差太大(例如:一个是常量时间,一个是正无穷),则没必要进行分解。
- 可以通过 Runtime.getRuntime().availableProcessors()方法获得当前设备的 CPU 个数。
根据“任务的优先级”分析
优先级不同的任务可以使用优先级队列 PriorityBlockingQueue 来处理。它可 以让优先级高的任务先执行。
根据“任务的执行时间”分析
执行时间不同的任务可以交给不同规模的线程池来处理,或者可以使用优先 级队列,让执行时间短的任务先执行。
根据“任务的依赖性(依赖数据库连接)”分析
依赖数据库连接池的任务,因为线程交 SQL 后需要等待数据库返回结果, 等待的时间越长,则 CPU 空闲时间就越长,那么线程数应该设置得越大,这样 才能更好地利用 CPU。
建议使用有界队列
有界队列能增加系统的稳定性和预警能力,可以根据需 要设大一点儿,比如几千。
假设,我们现在有一个 Web 系统,里面使用了线程池来处理业务,在某些 情况下,系统里后台任务线程池的队列和线程池全满了,不断抛出抛弃任务的异 常,通过排查发现是数据库出现了问题,导致执行 SQL 变得非常缓慢,因为后台 任务线程池里的任务全是需要向数据库查询和插入数据的,所以导致线程池里的 工作线程全部阻塞,任务积压在线程池里。
如果当时我们设置成无界队列,那么线程池的队列就会越来越多,有可能会 撑满内存,导致整个系统不可用,而不只是后台任务出现问题。
posted on 2020-09-13 22:27 frank_cui 阅读(1658) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?