scheduledexecutorservice 是 java 中用于延迟和周期性任务的线程池接口,比 timer 更健壮线程安全;支持 newscheduledthreadpool 和 newsinglethreadscheduledexecutor 创建;提供 schedule、scheduleatfixedrate、schedulewithfixeddelay 三种调度方式;需调用 shutdown() 和 awaittermination() 正确关闭;注意任务异常、执行超时及调度策略差异。

ScheduledExecutorService 是 Java 并发包(java.util.concurrent)中用于执行**延迟任务**和**周期性任务**的线程池接口,它比传统 Timer 更健壮、线程安全,且支持灵活的调度策略。
创建 ScheduledExecutorService 实例
通常通过 Executors 工具类创建:
-
Executors.newScheduledThreadPool(int corePoolSize):最常用,可配置核心线程数,适合多数场景; -
Executors.newSingleThreadScheduledExecutor():单线程调度器,保证任务串行执行,避免并发干扰; - 不推荐直接使用
new ScheduledThreadPoolExecutor(...),除非需要精细控制拒绝策略或队列等。
提交定时任务的三种方式
所有方法都返回 ScheduledFuture>,可用于取消或查询状态:
-
schedule(Runnable command, long delay, TimeUnit unit):延迟执行一次; -
schedule(Callable<v> callable, long delay, TimeUnit unit)</v>:延迟执行一次并获取返回值; -
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):固定速率执行(从上一次开始时间起算); -
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):固定延迟执行(从上一次结束时间起算)。
例如,每 3 秒执行一次,首次延迟 1 秒:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.scheduleAtFixedRate(() -> {
System.out.println("执行中:" + System.currentTimeMillis());
}, 1, 3, TimeUnit.SECONDS);
正确关闭线程池
不关闭会导致 JVM 无法正常退出(线程池中的线程是守护线程以外的非守护线程):
- 调用
shutdown():停止接收新任务,等待已有任务完成; - 配合
awaitTermination(long timeout, TimeUnit unit)等待终止,超时后可调用shutdownNow()尝试中断运行中任务; - 务必在 finally 块或 try-with-resources(需自行包装)中关闭。
注意事项与常见坑
- 如果任务执行时间 > 周期间隔,
scheduleAtFixedRate会“追赶”执行(可能连续触发),而scheduleWithFixedDelay会等上一次执行完再延后固定时间; - 任务抛出未捕获异常会导致该任务后续不再执行(但线程池仍存活),建议在
Runnable内加try-catch; - 不要在定时任务中长期阻塞或做耗时 IO,否则影响其他任务调度精度;
- 若需动态增删任务,可将
ScheduledFuture保存起来,调用cancel(true)终止。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











