Java中的ScheduledExecutorService是java.util.concurrent包提供的接口,用于替代传统的Timer来实现定时任务和延迟任务调度。它基于线程池机制,能够避免Timer单线程模型的诸多缺陷,更适合生产环境使用。

为什么不使用Timer
Timer内部只有一个工作线程,如果某个任务执行时间过长或者抛出未捕获异常,会影响后续任务甚至导致整个定时器失效。此外,Timer对系统时间变更敏感,不适合精确可靠的调度场景。
ScheduledExecutorService核心方法
通过Executors工厂类可以创建调度线程池,常用方法如下:
- schedule:延迟一段时间后执行一次任务
- scheduleAtFixedRate:以固定频率周期性执行任务
- scheduleWithFixedDelay:在上一次任务结束后固定延迟再执行下一次
创建调度线程池
下面代码展示如何创建一个大小为2的调度线程池并提交延迟任务:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Demo {
public static void main(String[] args) {
// 创建含有2个线程的调度线程池
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// 延迟3秒后执行一次任务
scheduler.schedule(() -> {
System.out.println("延迟任务执行,时间:" + System.currentTimeMillis());
}, 3, TimeUnit.SECONDS);
// 固定频率每5秒执行,初始延迟1秒
scheduler.scheduleAtFixedRate(() -> {
System.out.println("周期任务执行");
}, 1, 5, TimeUnit.SECONDS);
}
}
异常隔离优势
在ScheduledExecutorService中,每个任务由线程池中的线程独立运行。某个任务抛出RuntimeException不会导致整个调度器停止,其他任务依旧按计划执行,这是相比Timer最实用的改进。
如何选择调度方式
如果任务执行时间可能超过周期间隔,scheduleAtFixedRate会出現任务叠加,而scheduleWithFixedDelay能保证上次结束后再等待延迟时间,更适合不稳定耗时的任务。
| 对比项 | Timer | ScheduledExecutorService |
|---|---|---|
| 线程模型 | 单线程 | 线程池 |
| 异常影响 | 终止整体调度 | 仅影响当前任务 |
| 时间敏感 | 受系统时间影响 | 基于相对时间 |
小结
对于新项目,应优先使用ScheduledExecutorService而非Timer。它提供了更合理的并发模型与更完善的异常处理,是Java中处理延迟与定时任务的可靠利器。
ScheduledExecutorServiceTimer定时任务修改时间:2026-07-28 07:15:16