定时任务线程池-scheduleAtFixedRate和scheduleWithFixedDelay
- 前言
- 一、核心区别
- 二、源码处看区别
-
- [2.1 提交任务的源码区别](#2.1 提交任务的源码区别)
- [2.2 任务执行后的区别](#2.2 任务执行后的区别)
-
- [2.2.1 ScheduledFutureTask 的 run](#2.2.1 ScheduledFutureTask 的 run)
- [2.2.2 setNextRunTime](#2.2.2 setNextRunTime)
- 三、代码示例
-
- [3.1 scheduleAtFixedRate 执行时间大于间隔](#3.1 scheduleAtFixedRate 执行时间大于间隔)
前言
本章节介绍定时任务线程池中
scheduleAtFixedRate和scheduleWithFixedDelay的区别
一、核心区别
scheduleAtFixedRate是固定的频率执行,如果任务执行时间过程超过了固定频率需要注意不会并行执行,而是上个任务结束后立即执行下个任务scheduleWithFixedDelay是固定的延迟执行,上一个任务执行完成后多长时间再次执行
二、源码处看区别
2.1 提交任务的源码区别

2.2 任务执行后的区别
ScheduledFutureTask是最终提交给线程池的任务类,肯定实现了 Runnable 或者 Callable,其实是 Runnable,所以任务执行的时候肯定会执行它的run()
2.2.1 ScheduledFutureTask 的 run
java
public void run() {
if (!canRunInCurrentRunState(this))
cancel(false);
else if (!isPeriodic())
super.run();
// super.runAndReset 这里面会执行你提交的任务
// 注意这里是同步的, 也就是说 setNextRunTime 是在当前任务结束后才会执行, 因此同一个任务不会并行执行
else if (super.runAndReset()) {
// 设置下次执行时间
setNextRunTime();
reExecutePeriodic(outerTask);
}
}
2.2.2 setNextRunTime
java
private void setNextRunTime() {
long p = period;
// 如果 period > 0, 是上次开始执行时间+间隔
if (p > 0)
time += p;
else
// 如果 period<0, 则是需要重新计算下次执行时间
time = triggerTime(-p);
}
三、代码示例
3.1 scheduleAtFixedRate 执行时间大于间隔
java
@Test
public void test2() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
AtomicInteger counter = new AtomicInteger(1);
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
int currentNumber = counter.getAndIncrement();
// 这里日志要打印时间戳, 否则没有效果
log.info("AtFixed - start - {}", currentNumber);
ThreadUtil.sleep(5L, TimeUnit.SECONDS);
log.info("AtFixed - end - {}", currentNumber);
}, 0, 2, TimeUnit.SECONDS);
ThreadUtil.waiting();
}