scheduledexecutorservice 是 java 并发包中用于延迟和周期性任务调度的线程池接口,扩展了 executorservice 的定时能力,提供 scheduleatfixedrate(固定频率)和 schedulewithfixeddelay(固定延迟)两种周期执行方式,需通过 executors 创建,使用时须注意异常处理、任务取消、资源释放及不支持 cron 表达式等要点。

ScheduledExecutorService 是 Java 并发包(java.util.concurrent)中专用于**延迟执行和周期性任务调度**的线程池接口,它在 ExecutorService 基础上扩展了定时能力,比手动用 Timer 或循环 Thread.sleep() 更可靠、线程安全且支持拒绝策略。
核心方法:如何提交周期性任务
主要靠两个关键方法:
-
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):
首次延迟initialDelay后开始执行,之后**每间隔period时间固定触发一次**(从上一次任务**开始时间**算起)。即使某次任务执行超时,下一次仍按原节奏启动,可能造成任务重叠。 -
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):
首次延迟后执行,之后**在上一次任务**完成后,再等待delay时间才启动下一次。不会重叠,适合执行耗时不确定、需严格串行的场景。
创建方式:推荐使用 Executors 工具类
不能直接 new,需通过 Executors 创建:
-
Executors.newScheduledThreadPool(int corePoolSize):最常用,创建可扩容的调度线程池(核心线程数固定,空闲线程不销毁)。 -
Executors.unconfigurableScheduledExecutorService(ScheduledExecutorService):返回不可修改的包装实例(一般不用)。 - ⚠️ 注意:
Executors.newSingleThreadScheduledExecutor()本质是单线程池,适合顺序强依赖任务;但若一个任务阻塞或异常未捕获,后续所有任务都会被卡住。
实际使用要点与避坑提醒
使用时要注意几个关键细节:
-
异常必须显式处理:调度任务中抛出未捕获异常会导致该任务线程终止,后续周期不再触发。务必在
run()内加try-catch,或重写ThreadFactory设置默认异常处理器。 -
取消任务用
ScheduledFuture.cancel(boolean mayInterruptIfRunning):
传true可尝试中断正在运行的任务(需任务本身响应中断);false则只取消等待中的执行。 -
线程池记得 shutdown:长期运行的应用中,若不再需要调度器,应调用
shutdown()或shutdownNow()释放资源,否则 JVM 无法正常退出。 -
不支持 cron 表达式:如需类似 Linux cron 的复杂调度(如“每月第一个周一”),需配合第三方库(如 Quartz)或自行解析 cron 后转换为
scheduleAtFixedRate的组合逻辑。
简单示例:每 3 秒打印一次当前时间(固定速率)
(生产环境建议用日志框架代替 System.out)
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
ScheduledFuture> future = scheduler.scheduleAtFixedRate(() -> {
System.out.println("执行中: " + LocalDateTime.now());
}, 1, 3, TimeUnit.SECONDS); // 延迟 1 秒后开始,每 3 秒一次
// 10 秒后停止
scheduler.schedule(() -> {
System.out.println("取消任务");
future.cancel(true);
}, 10, TimeUnit.SECONDS);
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











