线程池参数到底要怎么配?这可能是最好的答案

您所在的位置:网站首页 AMD7002cpu参数 线程池参数到底要怎么配?这可能是最好的答案

线程池参数到底要怎么配?这可能是最好的答案

2024-01-04 16:00| 来源: 网络整理| 查看: 265

想必大家对Java里面线程池( ThreadPoolExecutor类)一定不陌生吧,无论是在日常工作还是面试题里都经常会有它的身影,特别是在当前CPU动辄就是好多核的背景下,了解并使用线程池已经成为一名合格后端开发的基本功了。 相信大家也一定思考过一个问题,面对各种各样的场景,线程池的参数到底应该怎么设计呢?这一定是一个超级难以回答的问题,几天前的我也想不到一个标准的答案,好在是发现了美团在2020年发表过的一篇文章,里面给了一个非常高级的操作——让线程池的参数动态化,这就极大地提高了系统的自适应能力。 tech.meituan.com/2020/04/02/… 至于为什么我现在才看到=_=,可能因为是太懒了吧。。。好在及时发现,在此基础上进行一些分析,不理解线程池的小伙伴们也不用担心,我们首先来回顾一下它的核心思想,在此技术上介绍如何将参数动态化起来~ 1 线程池快速回顾 《Java 并发编程的艺术》中提到了使用线程池的好处,概括起来如下:

降低资源损耗。通过重复利用已创建的线程降低线程创建和销毁的损耗。提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。使用线程池可以进行统一的分配,调优和监控。

Java里使用线程池,主要就是用的ThreadPoolExecutor类,先来看一下 ThreadPoolExecutor 类中的构造方法:

/** * 用给定的初始参数创建一个新的ThreadPoolExecutor。 */ public ThreadPoolExecutor(int corePoolSize,//线程池的核心线程数量 int maximumPoolSize,//线程池的最大线程数 long keepAliveTime,//当线程数大于核心线程数时,多余的空闲线程存活的最长时间 TimeUnit unit,//时间单位 BlockingQueue workQueue,//任务队列,用来储存等待执行任务的队列 ThreadFactory threadFactory,//线程工厂,用来创建线程,一般默认即可 RejectedExecutionHandler handler//拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务 ) { if (corePoolSize < 0 || maximumPoolSize 2 现有设置参数的方法及不足

回顾完线程池的核心技术点之后就要开始思考本文主要讨论的内容了:线程池参数应该如何设置?

如果你把这个问题输入到浏览器里,极大可能是下面这种答案:

上面的理论看似很华丽,但现实却是很残酷的。。。你会发现虽然按照上面的指导思想进行配置了,但效果并不能让人满意,造成这种后果的原因有很多,包括但不仅限于:

任务到底是CPU还是IO密集的特征不明显同一个机器上可能部署不止一个服务,不同服务之间也会抢占资源

针对上述问题,美团给出的对应的解决方案就是——线程池参数动态化 那么如何实现参数动态化呢? 接触过微服务开发的同学们可能就会想到了,我们完全可以借助一个配置中心来做,这样就能够实现线程池参数的动态配置和即时生效(在阿里内部也有一个专门的中间件,diamond),省去了重新部署程序并发布的步骤,通常在企业里这一系列流程下来还是比较费时间的。

3 如何设置核心线程数(corePoolSize)

其实 ThreadPoolExecutor 类库里直接就有这个方法:

public void setCorePoolSize(int corePoolSize) { if (corePoolSize < 0) throw new IllegalArgumentException(); int delta = corePoolSize - this.corePoolSize; this.corePoolSize = corePoolSize; if (workerCountOf(ctl.get()) > corePoolSize) interruptIdleWorkers(); else if (delta > 0) { // We don't really know how many new threads are "needed". // As a heuristic, prestart enough new workers (up to new // core size) to handle the current number of tasks in // queue, but stop if queue becomes empty while doing so. int k = Math.min(delta, workQueue.size()); while (k-- > 0 && addWorker(null, true)) { if (workQueue.isEmpty()) break; } } }

我们直接看英文注释,这就是作者直接想要表达的意思。大致翻译一下: 设置线程的核心数量,如果新的corePoolSize值小于当前corePoolSize值,多出来的线程将在其下次空闲时被终止。如果新的corePoolSize值大于当前corePoolSize值,就可以创建新的worker来执行队列里的任务

4 如何设置最大线程数(maxPoolSize)

同样地 ThreadPoolExecutor 类库里也有这个方法:

public void setMaximumPoolSize(int maximumPoolSize) { if (maximumPoolSize maximumPoolSize) interruptIdleWorkers(); }

这个方法的注释和上面的方法类似,大家可以对照着看:

逻辑也并不复杂:

参数校验设置最大线程数 maxPoolSize如果工作线程数是否大于最大线程数,则对空闲线程发起中断

JDK原生线程池ThreadPoolExecutor还提供了其他设置参数的方法:

5 如何改变等待队列长度

等待队列的长度capacity被final修饰符修饰,所以按理说是不能修改的

private static final int CAPACITY = (1

Python入门大全套!更适合初学者的Python从业速成计划!两个月可上岗那种!_哔哩哔哩_bilibili

可以写在简历上的项目合集,2022最新版Java初阶实战项目合集,手把手教你建立多个系统项目



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3