如何监控线程池任务从执行开始的超时情况,且提交方法不阻塞
问题判断
你的判断完全正确。Future#get(timeout)的超时统计周期从调用get方法的时刻开始计算,既不匹配你要求的「任务实际启动后开始统计」的规则,同时调用get会阻塞当前线程,不符合acceptNewJob提交后立即返回的要求。
实现方案
推荐用「业务任务包裹计时+独立调度线程池做超时检测」的方案,无阻塞、逻辑轻量,完全满足需求:
核心思路
- 额外创建一个单例的
ScheduledExecutorService,仅用于调度超时告警任务,不会影响业务线程池的执行 - 业务任务
run方法启动的第一时间,向调度线程池提交一个延迟任务,延迟时长就是当前任务的超时时间,延迟任务的逻辑为超时告警 - 业务任务执行完成(正常结束/抛出异常结束)后,立即取消上述延迟告警任务即可:如果业务执行耗时未超时,告警任务会被直接取消不会触发;如果执行超时,告警任务会在延迟到期后正常触发
代码实现
import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; public class JobManager { // 业务线程池 private final ExecutorService businessPool = Executors.newFixedThreadPool(10); // 超时检测调度线程池,单线程即可,仅做调度逻辑 private final ScheduledExecutorService timeoutChecker = Executors.newSingleThreadScheduledExecutor(); public void acceptNewJob(Map<String, Object> params) { int timeoutInMs = (int) params.get("timeoutInMs"); // 提交业务任务,方法无阻塞直接返回 businessPool.submit(new Runnable() { @Override public void run() { // 用于保存超时告警任务的Future,原子引用保证多线程可见性 AtomicReference<Future<?>> alarmFutureRef = new AtomicReference<>(); try { // 任务实际启动,立即注册超时告警任务 Future<?> alarmFuture = timeoutChecker.schedule(() -> { // 此处写超时告警逻辑,比如上报监控、发通知等 System.out.println("任务执行超时,超时阈值:" + timeoutInMs + "ms"); }, timeoutInMs, TimeUnit.MILLISECONDS); alarmFutureRef.set(alarmFuture); // ------------------- 原有业务逻辑 ------------------- // generate a job by params // ------------------- 原有业务逻辑 ------------------- } finally { // 业务执行结束,取消超时告警任务 Future<?> alarmFuture = alarmFutureRef.get(); if (alarmFuture != null && !alarmFuture.isDone()) { // 参数false表示如果告警任务已经在执行,不需要中断,仅取消未执行的告警任务 alarmFuture.cancel(false); } } } }); } }
扩展说明
- 如果需要在超时后中断还在运行的业务任务,可以在超时告警任务中保存当前业务线程的引用,超时后调用线程的
interrupt()方法即可,业务逻辑中需要响应中断信号 - 超时告警逻辑不要做耗时操作,如果需要执行复杂告警逻辑,可以再提交到独立的异步线程池处理,避免阻塞超时检测调度线程
- 如果你的项目使用了Spring框架,也可以直接用
@Async注解结合自定义的超时监听器实现,核心逻辑和上述方案一致
内容的提问来源于stack exchange,提问作者エンターテインメント
相关产品推荐
相关产品推荐

