You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ScheduledExecutorService调用shutdown后仍运行任务的原因是什么?

问题原因

  • 最核心的原因是cancel(false)的参数配置错误:cancel方法的入参mayInterruptIfRunning设为false时,仅会取消还未开始调度的任务,不会中断已经处于运行状态的任务。你用的是scheduleWithFixedDelay提交的周期性任务,若调用cancel时正好有任务在执行,该任务会正常跑完当前逻辑才会终止,你就会观测到shutdown后仍有Runnable在运行。
  • scheduledFutures使用了非线程安全的ArrayList:如果存在并发调用execute提交任务、同时触发shutdown的场景,遍历列表时可能出现并发修改异常,甚至部分刚提交的ScheduledFuture没被遍历到,导致对应的任务没有被取消,持续运行。
  • 任务本身可能不响应中断:就算后续调用shutdownNow会尝试中断所有运行中的线程,如果你的Runnable逻辑里吞了InterruptedException、没有处理中断标记,中断信号不会生效,任务还是会继续执行。
  • awaitTermination仅等待1秒:如果正在运行的任务单次执行时长超过1秒,在等待超时前你观测到任务还在运行是符合预期的。

修复方案

  1. 将cancel的入参改为true,允许中断正在运行的任务
  2. 把scheduledFutures替换为线程安全的CopyOnWriteArrayList,避免并发操作异常
  3. 确保业务Runnable逻辑正确响应中断,不要吞中断异常
  4. 可选:开启线程池的setRemoveOnCancelPolicy配置,cancel任务后自动从队列移除,避免资源占用

修改后的参考代码:

public class ThreadPool {
    private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
    // 替换为线程安全容器
    private final List<ScheduledFuture<?>> scheduledFutures = new CopyOnWriteArrayList<>();

    public ThreadPool(ScheduledThreadPoolExecutor scheduledThreadPoolExecutor) {
        this.scheduledThreadPoolExecutor = scheduledThreadPoolExecutor;
        // 可选配置:任务被cancel后自动从调度队列移除
        this.scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true);
    }

    public void execute(Runnable runnable) {
        scheduledFutures.add(
            scheduledThreadPoolExecutor.scheduleWithFixedDelay(runnable, 0, 20, TimeUnit.SECONDS));
    }

    public void shutdown() {
        // 改为传true,允许中断运行中的任务
        scheduledFutures.forEach(scheduledFuture -> scheduledFuture.cancel(true));
        // 可选:cancel后清空列表,避免重复操作、内存泄露
        scheduledFutures.clear();
        scheduledThreadPoolExecutor.shutdown();
        try {
            // 可以根据业务任务的最大执行时长调整等待时间
            if (scheduledThreadPoolExecutor.awaitTermination(3, TimeUnit.SECONDS)) {
                return;
            }
            scheduledThreadPoolExecutor.shutdownNow();
        } catch (Exception exception) {
            Thread.currentThread().interrupt();
        }
    }
}

内容的提问来源于stack exchange,提问作者Zafiro Geta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:18:04