合理配置线程池的线程数量

前言

随着多核CPU的发展,多线程编程的应用越来越广泛,为了降低频繁创建线程,销毁线程所产生额外的资源开销,推出了线程池技术。使用线程池技术我们需要设置核心线程数与最大线程数,许多中间件也会将这两个参数交由我们自己设置,那么如何科学合理的去设置这两大参数呢?下面我们来一起研究一下。

方案

一般我们的程序都会分为以下几种类型,CPU密集型(计算密集型)、IO密集型、混合型,针每种类型的程序我们有不同的配置方案。

1 CPU密集型

CPU密集型也就是计算密集型,常常指算法复杂的程序,需要进行大量的逻辑处理与计算,CPU在此期间是一直在工作的。

在这种情况下CPU的利用率会非常高,我们的最大核心数设置为CPU的核心数即可。

这种情况下CPU几乎满负荷运行,我们配置的数字在大也没有效果,反而会增大额外的切换开销。

在《Java Concurrency in Practice》中,推荐将CPU密集型最大线程数设置为最大线程数 = CPU核心数 + 1,这样能发挥最高效率。

核心线程数一般会设置为 核心线程数 = 最大线程数 * 20%

如下图所示,CPU密集型更多的是计算任务会持续占用CPU。

image.png

2 IO密集型

IO密集型是指我们程序更多的工作是在通过磁盘、内存或者是网络读取数据,在IO期间我们线程是阻塞的,这期间CPU其实也是空闲的,这样我们的操作系统就可以切换其他线程来使用CPU资源。

通常在进行接口远程调用,数据库数据获取,缓冲数据获取都属于IO操作。

这时我们线程数可以通过以下公式进行计算:最大线程数 = CPU核心数 / (1 – 阻塞占百分比)

我们很好理解比如在某个请求中,请求时长为10秒,调用IO时间为8秒,这时我们阻塞占百分比就是80%,有效利用CPU占比就是20%,假设是八核CPU,我们线程数就是8 / (1 – 80%) = 8 / 0.2 = 40个。

也就是说 我们八核CPU在上述情况中,可满负荷运行40个线程。这时我们可将最大线程数调整为40,在系统进行IO操作时会去处理其他线程。

通常我们会设置为最大线程数 = CPU核心数 * 2

核心线程数一般会设置为 核心线程数 = 最大线程数 * 20%

如下图所示,IO密集型是同一个任务只有部分时间是在进行计算,很长时间都在进行IO阻塞。这样CPU同时刻就能处理更多的任务。

image.png

3 混合型

混合型程序,指既包含CPU密集型,又包含IO密集型。

对于此类程序,我们可以将任务划分成cpu密集型任务与IO密集型任务,分别针对这两种任务使用不同的线程池去处理。这样我们就可以针对这两种情况对线程池配置不同的参数。  

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享