oneThread动态线程池
作者:程序员马丁
热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。
🚀oneThread 轮子项目
1. 基础介绍
oneThread 是基于 配置中心 构建的动态可观测 Java 线程池框架,弥补了 JDK 原生线程池 参数配置不灵活的不足,支持核心参数的 在线动态调整、运行时状态监控 与 阈值告警,有效提升系统的稳定性与可运维性。框架兼容主流配置中心如 Nacos、Apollo,实现线程池参数的 热更新与统一管理。

目前后端核心代码(包含注释)1.34w 行,仅 Java 后端纯代码 4.99k 行。

2. 技术栈
Spring、Spring Boot、JUC、Tomcat、Jetty、Nacos、Apollo、Prometheus、Grafana
3. 为什么会有动态线程池?
3.1 任务执行拒绝
事故描述:XX页面展示接口产生大量调用降级,数量级在几十到上百。
事故原因:该服务展示接口内部逻辑使用线程池做并行计算,由于没有预估好调用的流量,导致最大核心数设置偏小,大量抛出 RejectedExecutionException,触发接口降级条件,示意图如下:

3.2 任务执行时间过长
事故描述:XX业务提供的服务执行时间过长,作为上游服务整体超时,大量下游服务调用失败。
事故原因:该服务处理请求内部逻辑使用线程池做资源隔离,由于队列设置过长,最大线程数设置失效,导致请求数量增加时,大量任务堆积在队列中,任务执行时间过长,最终导致下游服务的大量调用超时失败。示意图如下:

4. 教学亮点 & 技术实现——
4.1 动态参数刷新能力
基于配置中心实现线程池核心参数的动态刷新能力,采用模板方法模式复用刷新逻辑,支持多种配置中心(如 Nacos、Apollo)监听事件的统一注册与处理,提升代码复用和扩展性。
线程池动态变更原理如下图所示:

线程池参数在配置中心定义如下所示:
onethread:
nacos:
data-id: onethread-nacos-cloud-example-ding-ma.yaml
group: DEFAULT_GROUP
config-file-type: YAML
web:
core-pool-size: 20
maximum-pool-size: 400
keep-alive-time: 60
notify:
receives: xxxxxx
notify-platforms:
platform: DING
url: https://oapi.dingtalk.com/robot/send?access_token=xxxxxx
executors:
- thread-pool-id: onethread-producer
core-pool-size: 12
maximum-pool-size: 18
queue-capacity: 2000
work-queue: ResizableCapacityLinkedBlockingQueue
rejected-handler: CallerRunsPolicy
keep-alive-time: 60
allow-core-thread-time-out: false
notify:
receives: xxxxxx
interval: 10
alarm:
enable: true
queue-threshold: 80
active-threshold: 80
发起参数变更后:

4.2 拒绝策略增强机制
基于 JDK 的 InvocationHandler 实现动态代理机制,对线程池拒绝策略进行代理扩展,拦截拒绝任务事件并触发告警机制,实现任务拒绝的实时响应。
@AllArgsConstructor
public class RejectedProxyInvocationHandler implements InvocationHandler {
private final Object target;
private final AtomicLong rejectCount;
private static final String REJECT_METHOD = "rejectedExecution";
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (REJECT_METHOD.equals(method.getName()) &&
args != null &&
args.length == 2 &&
args[0] instanceof Runnable &&
args[1] instanceof ThreadPoolExecutor) {
rejectCount.incrementAndGet();
}
if (method.getName().equals("toString") && method.getParameterCount() == 0) {
return target.getClass().getSimpleName();
}
try {
return method.invoke(target, args);
} catch (InvocationTargetException ex) {
throw ex.getCause();
}
}
}
监控线程池运行状态异常告警如下所示:
