一、本质区别
- Timer
- JDK 1.3 就有的单线程定时任务
- 内部只有一个线程轮流执行所有任务
- 基于绝对系统时间
System.currentTimeMillis()
- ScheduledExecutorService
- JDK 1.5 JUC 并发包提供
- 线程池,多个线程执行任务
- 基于相对时间(纳秒),不依赖系统时间
- 任务之间完全隔离
二、核心缺陷对比
-
Timer 单线程,一个任务卡死,全部任务卡死
-
Timer 任务抛出未捕获异常 → 整个 Timer 直接死亡
-
Timer 依赖系统时间,改时间会导致任务执行异常
-
ScheduledExecutorService 完全解决以上所有问题
三、代码案例对比
① Timer 代码示例
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
// 任务1:正常执行
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("任务1执行");
}
}, 0, 1000);
// 任务2:10秒后抛异常
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("任务2抛出异常");
// Timer 只要有一个任务抛异常,整个Timer线程死亡!所有任务停止!
throw new RuntimeException("异常");
}
}, 3000);
}
}
运行结果:
任务 1 执行几次 → 任务 3 秒后抛异常 → 整个程序所有定时任务全部停止!
② ScheduledExecutorService 代码示例
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledTest {
public static void main(String[] args) {
// 核心线程池2个
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// 任务1:正常执行
executor.scheduleAtFixedRate(() -> {
System.out.println("任务1执行");
}, 0, 1, TimeUnit.SECONDS);
// 任务2:3秒后抛异常
executor.schedule(() -> {
System.out.println("任务2抛出异常");
throw new RuntimeException("异常");
}, 3, TimeUnit.SECONDS);
}
}
运行结果:
任务 2 抛出异常 只影响自己! 任务 1 永远继续执行!
ScheduledExecutorService
Java 1.5 提供的 **** 线程池风格的定时任务工具 ,用来替代旧的 Timer 。父接口是 ExecutorService,所以本质就是一个支持延迟 / 周期性执行的线程池。
常用方法
-
schedule(Runnable, delay, unit)
延迟一段时间执行一次
-
scheduleAtFixedRate(Runnable, initialDelay, period, unit)
固定速率执行 ,每隔 period 执行一次,不关心任务执行时长
-
scheduleWithFixedDelay(Runnable, initialDelay, delay, unit)
固定间隔执行 ,任务执行结束后,再等 delay 才执行下一次
-
schedule(Callable...)
延迟执行并带返回值
最核心区别
FixedRate:固定频率
每隔 固定时间 启动一次,任务执行时间长会导致任务挤堆、并发执行。
FixedDelay:固定延迟
任务结束 → 等延迟 → 再执行下一次 任务之间一定有固定空闲时间。
优点(对比 Timer)
- Timer 是单线程,一个任务卡死全部卡死
- ScheduledExecutorService 是线程池,任务之间隔离
- 任务抛出异常不会杀死整个调度器
- 更精确、更稳定
底层是什么?
**内部用的是:DelayedWorkQueue(延迟阻塞队列)**按执行时间排序,线程不断拿 "到时间" 的任务执行。
面试一句话总结
ScheduledExecutorService 是 JUC 提供的基于线程池的定时任务组件,用来替代 Timer,支持延迟执行、固定频率、固定间隔三种定时策略;任务隔离、异常安全,底层基于延迟队列实现。