一、起因:
在使用ScheduledThreadPoolExecutor执行一个定时任务时,发现执行一次后,任务就不再执行。
代码举例:
private static final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1);
private static final CountDownLatch countDownLatch =
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
executorService.scheduleAtFixedRate(() -> {
System.out.println("task");
//test() 调用第三方接口
}, 0, 2, TimeUnit.SECONDS);
// executor();
countDownLatch.await();
}
代码走到调用第三方接口后,三方接口内日志只打印了部分,推测接口没有执行完就出错了,测试后发现第三方项目没有启动,连接超时,所以调用失败,但是为啥没有报错日志,异常日志被吞。
二、ScheduledThreadPoolExecutor源码分析
(1)ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,先看scheduleAtFixedRate方法
1、
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
//这里把我们传的Runnable封装成了一个FutureTask对象
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
unit.toNanos(period));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
return t;
}
2、
ScheduledFutureTask(Runnable r, V result, long ns, long period) {
super(r, result);
this.time = ns;
this.period = period;
this.sequenceNumber = sequencer.getAndIncrement();
}
//在进入 super(r, result);
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this