可通过继承ThreadPoolExecutor重写beforeExecute(记录起始时间、更新活跃数)、afterExecute(统计耗时/成败、累计指标)、rejectedExecution(告警拒绝)及定时打印快照,实现轻量级线程池可观测性监控。

可以通过继承 ThreadPoolExecutor 并重写 beforeExecute 和 afterExecute 方法,在任务执行前后注入轻量级监控逻辑,配合原子变量统计和定时打印,实现运行指标的可观测输出。
重写 beforeExecute 记录任务起点
该方法在任务真正开始执行前被调用,适合埋点记录起始时间、线程身份等上下文信息:
- 使用
ThreadLocal<Long>存储每个任务的开始时间戳(推荐System.nanoTime(),避免时钟回拨) - 可同步更新活跃任务计数器,例如:
activeTaskCount.incrementAndGet() - 避免在此处做日志打印、I/O 或远程调用,仅做内存操作以保障性能
重写 afterExecute 汇总执行结果
无论任务成功或抛出异常,该方法都会被调用,是统计耗时、成功率和异常的关键位置:
- 从
ThreadLocal取出开始时间,结合System.nanoTime()计算精确耗时 - 根据是否传入
Throwable判断执行成败,更新失败计数器 - 调用
completedTaskCount.incrementAndGet()和totalCost.addAndGet(cost)累计指标 - 可在此触发阈值判断,如耗时超 1000ms 时记录 warn 日志
暴露指标并定时打印
在自定义线程池类中提供安全读取接口,并搭配简单定时任务输出快照:
立即学习“Java免费学习笔记(深入)”;
- 封装
getActiveCount()、getQueue().size()、getCompletedTaskCount()等标准方法的增强版 - 新增
getAvgExecutionTime(),用累计耗时除以完成数(注意除零保护) - 用
ScheduledExecutorService每 10 秒调用一次打印逻辑,输出类似:
[MonitoredPool] active=3, queue=12, completed=2487, avg=42ms, rejects=0
补充 rejectedExecution 实现拒绝告警
当任务被拒绝时,该方法会被触发,可用于识别容量瓶颈:
- 原子递增拒绝计数器:
rejectedCount.incrementAndGet() - 打印带堆栈的告警日志,包含当前队列大小、活跃线程数等上下文
- 区分拒绝策略类型(如
AbortPolicyvsCallerRunsPolicy),不同策略反映不同问题信号



















