多线程 - 如何合理配置线程池

回到顶部(go to top)

总结

根据“任务的性质”分析

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   frank_cui  阅读(1658)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

levels of contents
点击右上角即可分享
微信分享提示