前言
最近开市场问题,发现程序中同时开启的四个定时任务只有一个还在执行,后面跟踪原因,发现是ScheduledExecutorService在遇到异常时候会抑制后续任务的执行。
一、ScheduledExecutorService#scheduleAtFixedRate方法注释
后半段主要说明以下三点:
- 如果某一次过程中产生异常,则会抑制后续任务的执行
- 正常情况下,该定时任务只会通过取消和终止执行者停止
- 如果一次任务的实际执行时间比方法中给定的周期还长,那么下次任务会等该次任务执行结束后再开始,且保证不会并发执行
二、本地验证
1.不捕获异常
代码如下(示例):
public static void main11() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
LongAdder longAdder = new LongAdder();
scheduledExecutorService.scheduleAtFixedRate(() -> {
longAdder.add(1L);
System.out.println(longAdder.longValue() + " 次任务开始执行");
if (longAdder.longValue() >= 3) {
System.err.println(longAdder.longValue() + " 次任务执行过程中抛出异常");
System.err.println("异常" + 1 / 0);
}
}, 1, 1, TimeUnit.MILLISECONDS);
}
运行结果:
任务还在继续运行,但是后续的执行因为异常的产生被抑制。
2.捕获异常(注意使用Throwable)
代码如下(示例):
public static void main12() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
LongAdder longAdder = new LongAdder();
scheduledExecutorService.scheduleAtFixedRate(() -> {
longAdder.add(1L);
System.out.println(longAdder.longValue() + " 次任务开始执行");
if (longAdder.longValue() >= 3) {
// 增加了try-catch,注意这里最好使用Throwable,防止漏掉Error
try {
System.err.println("构造异常" + 1 / 0);
} catch (Throwable e) {
System.err.println(longAdder.longValue() + " 次任务执行过程中抛出异常" + e.getMessage());
}
}
}, 1, 1, TimeUnit.MILLISECONDS);
}
运行结果:
手动停止进程后,进行截图,如果不手动停止该任务一直运行。