【JUC进阶】如何合理设置线程池核心线程数?

1. 前言

线程池(Thread Pool)是一种基于池化思想管理线程的工具,线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。

因此,线程池的参数的合理化就会显得很重要了。

如果核心线程数设置偏小,那么会大量抛出RejectedExecutionException,触发接口降级条件。

img

如果核心线程设置偏大,可能会导致核心线程并没有重复利用,但是程序还需要维护这些线程,因此导致了资源的浪费。

如果线程池队列长度设置过长、corePoolSize设置过小导致任务执行速度低

img

这时候就要根据程序是IO密集型还是CPU密集型来决定核心线程数了。


2. CPU 密集型

CPU密集型,是指CPU使用频率比较高,也就是CPU经常计算一些复杂的运算、逻辑处理等。

在CPU密集型的情况下,CPU负载比较高,而IO在很短时间就完了。

就比如一个计算圆周率至小数点一千位以下的程序,在执行的过程当中绝大部份时间用在三角函数和开根号的计算,这种就是典型的CPU密集型。

这时候,线程数一般只需要设置为CPU核心数的线程个数就可以了。


3. IO密集型

IO密集型,指的是CPU使用率比较低,程序大部分时间都是用在等待IO的读或写,导致线程空余时间很多。

这种情况下,核心线程数量一般设置为CPU核心数的两倍。

当线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率。

  1. 线程等待时间所占比例越高,需要越多线程,启用其他线程继续使用CPU,以此提高CPU的利用率;
  2. 线程 CPU 时间所占比例越高,需要越少的线程,这一类型在开发中主要出现在一些计算业务频繁的逻辑中。

4. 实际情况

但是实际情况是根据并发任务的执行情况和任务类型相关,IO密集型和CPU密集型的任务运行起来的情况差异非常大,但这种占比是较难合理预估的,这导致很难有一个简单有效的通用公式帮我们直接计算出结果。

对于这种情况我们可以参考美团技术团队线程池参数动态化来实现。

有兴趣的同学可以阅读这篇文章——Java线程池实现原理及其在美团业务中的实践 - 美团技术团队 (meituan.com)


猜你喜欢

转载自blog.csdn.net/weixin_51146329/article/details/129642700