今天,说一说线程池 “动态更新”(三)

Handpc
发布于 2022-6-23 17:05
浏览
0收藏

 

动态的阻塞队列
线程池中是以 生产者消费者模式,通过一个阻塞队列来缓存任务,工作线程从阻塞队列中获取任务。工作队列的接口是阻塞队列(BlockingQueue),在队列为空时,获取元素的线程会 等待队列变为非空,当队列满时,存储元素的线程会 等待队列可用

阻塞队列动态设置队列大小,有很多种操作方式。可以按照原逻辑不变加一些扩展,也可以在特定方法上进行重写,实现方式并不固定。下面说几种可以实现动态阻塞队列功能的方案

  1. 复制阻塞队列源代码实现,添加 #set 方法使 capacity 可变
  2. 继承阻塞队列,并在原基础上重写核心方法
  3. 继承阻塞队列,反射动态修改 capacity
    如果不需要重写原阻塞队列获得额外的功能,小编更倾向于第一种,代码上会更简洁一些,并且稳定

 

复制阻塞队列
这一种方式简单粗暴,直接把 LinkedBlockingQueue 代码复制出来一份,改个新名字 ResizableCapacityLinkedBlockIngQueue,然后把 capacity 所修饰的 final 关键字去掉,再加上一个 #setCapacity 方法

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
重写核心方法
网上大多数博主使用的都是上述复制阻塞队列的方式,后来和两位大佬讨论阻塞队列的动态,然后从 GitHub 上发现了一位国外程序员的版本,通过信号量的方式控制阻塞队列的大小,《GitHub LinkedBQ 信号量实现》[3]

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
队列中包含阻塞 队列的大小以及自实现的信号量。每次进行调整阻塞队列大小的同时也对信号量进行增减

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
反射修改 Capacity
通过反射的方式同样可以达到阻塞队列动态修改的功能。在修改之前,有考虑过这种方式 会不会存在线程不安全的问题,对此使用 Jmeter 线程组和修改 capacity 交替操作,进行了几轮测试,测试的结论是 不存在线程安全问题

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
对于使用反射修改阻塞队列大小,小编是不推荐的。首先这种硬编码的方式并不优雅,其次并不能百分百保证能兼容后续 JDK 版本

综合考虑,虽然反射修改 capacity 可以达到理想中的效果,但是不建议这么做

总结一下
在文章中,小编总结了业界内使用线程池普遍存在的情况

  1. 线程池的 参数无法执行快速动态调整
  2. 没有合理的监控进而导致 失去主动权 以及 有效预防潜在问题

基于第一种动态参数调整的问题写下了动态线程池系列的第一篇文章。是的,后面会有更多的动态线程池文章,包括不限于以下几个 IDEA

  1. 线程池实时监控如何实现,历史指标数据 如何汇总 Admin 展示
  2. 对接不同平台的报警消息,达到 可配置、优雅的一发多收效果
  3. 动态线程池可不可以 对标配置中心,对接 Server 端统一管理触发参数修改
    上面这些功能,其实在美团的动态线程池里都有实现,奈何并没有开源。而自己项目中确实存在这方面的痛点,所以只有 重复造个轮子

最初,花了大概三天时间写出了一个依赖中间件的版本,并可以 完成对接平台化的动态线程池。可能是因为太简单了,觉得是不是缺了点什么。后来在一个睡不着的晚上脑洞大开,如果不依赖中间件是不是也行?

继而就有了动态线程池 DTP(Dynamic-ThreadPool)项目,并且给项目 groupId 起名 io 开头。目前而言的话,DTP 仅作为小编锻炼开发能力以及产品意识的项目,每天的代码开发时间集中在下班和周六天

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
DTP 项目分为两个主体,Server 和 SpringBoot Starter,Server 端作为所有客户端线程池的注册中心以及历史指标数据存储,供 Admin 调取展示,Starter 会作为 Jar 被客户端所依赖与 Server 端交互

目前 DTP 已实现 Server 端和 Client 端的 动态参数更新交互,源码实现参考借鉴了 Nacos 2.0 之前的 长轮询和事件监听机制

既然选择了不依赖中间件,那么问题也就显而易见了,线上环境的单点问题。因为一旦部署集群,数据在各节点之间无法流转广播,这一块后面可能会 参考 Eureka 做分布式的 AP 模型

 今天,说一说线程池 “动态更新”(三)-鸿蒙开发者社区
最后的最后,看了项目感觉还不错,辛苦小伙伴点个 ⚡️ Star,祝好。

代码还在持续更新,源码地址:https://github.com/acmenlt/dynamic-threadpool[4]

参考资料
[1]《Java线程池实现原理及其在美团业务中的实践》: https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html

[2]如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答: https://cloud.tencent.com/developer/article/1615007

[3]《GitHub LinkedBQ 信号量实现》: https://sourl.cn/7Uvw88

[4]点击阅读原文跳转 GitHub: https://github.com/acmenlt/dynamic-threadpool

 

文章转自公众号:龙台的技术笔记

已于2022-6-23 17:05:45修改
收藏
回复
举报
回复
    相关推荐