如何使用ScheduledExecutorService取消当前正在运行的定时任务?
取消周期性调度任务的实现方案
你不需要关闭executor实例即可终止指定周期任务,核心实现是调用ScheduledFuture自带的cancel()方法,该操作只会终止当前任务的后续调度,完全不影响线程池内其他任务的运行。
由于lambda表达式定义时scheduledTask还未完成赋值,无法直接在内部引用该变量,你可以通过AtomicReference包装解决引用时序问题,参考实现如下:
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.ScheduledFuture; // 原子引用存储ScheduledFuture实例 AtomicReference<ScheduledFuture<?>> taskRef = new AtomicReference<>(); ScheduledFuture<?> scheduledTask = _executor.scheduleWithFixedDelay(() -> { try { // 注意原代码判断逻辑写反:条件不成立时执行取消逻辑 if (!isValid()) { // 先执行自定义的任务关闭逻辑 // Do tasks to close // 取消周期任务,参数false表示不中断当前正在运行的任务,待本次逻辑执行完后不再生成后续任务 // 如果需要立刻中断当前任务的运行,可将参数改为true taskRef.get().cancel(false); } } catch (Throwable e) { log.fatal("Unexpected error..", e); // 异常场景也可选择取消任务,避免后续重复报错 taskRef.get().cancel(false); } }, 0L, 30, TimeUnit.SECONDS); // 将初始化完成的Future存入原子引用 taskRef.set(scheduledTask);
cancel方法参数说明
cancel(false):仅取消后续的调度计划,当前正在执行的本次任务会正常跑完所有逻辑,适配你的业务场景cancel(true):会向当前运行任务的线程发送中断信号,适合任务支持中断、需要立刻终止执行的场景
可选简化方案
如果不想引入原子引用,也可以在执行完关闭逻辑后主动抛出未捕获的RuntimeException,ScheduledExecutorService收到未捕获异常后会自动终止该任务的后续调度,也不会影响线程池的其他功能:
ScheduledFuture<?> scheduledTask = _executor.scheduleWithFixedDelay(() -> { try { if (!isValid()) { // Do tasks to close // 抛出异常终止后续调度 throw new RuntimeException("校验不通过,终止周期任务"); } } catch (RuntimeException e) { // 放行终止任务用的自定义异常 throw e; } catch (Throwable e) { log.fatal("Unexpected error..", e); throw new RuntimeException("任务执行异常,终止周期调度", e); } }, 0L, 30, TimeUnit.SECONDS);
内容的提问来源于stack exchange,提问作者Chillax
相关产品推荐
相关产品推荐

