一、Scheduled 注解简介Spring Framework 提供了强大的定时任务支持其中Scheduled注解是实现定时任务最常用的方式。通过在方法上添加此注解可以轻松配置任务在特定时间点或周期性地执行。基本使用示例import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; Component public class MyScheduledTask { Scheduled(fixedRate 5000) // 每5秒执行一次 public void executeTask() { System.out.println(定时任务执行 new Date()); } }要启用定时任务功能需要在配置类上添加EnableScheduling注解import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.context.annotation.Configuration; Configuration EnableScheduling public class SchedulingConfig { // 配置类 }二、Cron 表达式详解Cron 表达式是定义定时任务执行时间的强大工具由6个或7个字段组成Spring 支持6位Quartz 支持7位。2.1 Cron 表达式格式Spring 中 Cron 表达式的标准格式为秒 分 时 日 月 星期 [年]各字段的取值范围和特殊字符字段允许值允许的特殊字符秒Seconds0-59, - * /分Minutes0-59, - * /时Hours0-23, - * /日Day of month1-31, - * ? / L W月Month1-12 或 JAN-DEC, - * /星期Day of week0-7 或 SUN-SAT0和7都表示周日, - * ? / L #2.2 特殊字符说明*匹配任意值每秒钟、每分钟等?不指定值仅用于日和星期字段避免冲突-范围如 10-12 表示10、11、12,列举多个值如 MON,WED,FRI 表示周一、三、五/增量如 0/15 表示从0开始每15个单位L最后最后一天、最后一个星期几W工作日最近的工作日#第几个星期几如 6#3 表示第三个星期五2.3 常用 Cron 表达式示例表达式说明0 0 12 * * ?每天中午12点执行0 15 10 ? * *每天上午10:15执行0 0/5 14,18 * * ?每天下午2点到2:55期间和下午6点到6:55期间每5分钟执行一次0 0-5 14 * * ?每天下午2点到2:05期间每分钟执行一次0 0/30 9-17 * * MON-FRI工作日上午9点到下午5点每30分钟执行一次0 0 12 1 * ?每月1号中午12点执行0 15 10 15 * ?每月15号上午10:15执行0 15 10 L * ?每月最后一天上午10:15执行0 15 10 ? * 6L每月最后一个星期五上午10:15执行0 15 10 ? * 6#3每月第三个星期五上午10:15执行2.4 Scheduled 中使用 CronComponent public class CronScheduledTasks { // 每天凌晨1点执行 Scheduled(cron 0 0 1 * * ?) public void dailyTask() { System.out.println(每日任务执行 new Date()); } // 每30秒执行一次 Scheduled(cron 0/30 * * * * ?) public void every30Seconds() { System.out.println(每30秒执行 new Date()); } // 工作日每小时执行 Scheduled(cron 0 0 * * * MON-FRI) public void workHourTask() { System.out.println(工作日每小时执行 new Date()); } }三、多定时任务的执行顺序与优先级3.1 默认执行顺序Spring 默认使用单线程执行所有Scheduled任务这意味着任务按触发时间顺序进入执行队列同一时间只能执行一个任务如果前一个任务未执行完后续任务需要等待3.2 任务执行时间重叠问题Component public class OverlapTasks { Scheduled(fixedRate 2000) // 每2秒执行一次 public void taskA() throws InterruptedException { System.out.println(Task A 开始 new Date()); Thread.sleep(3000); // 模拟耗时3秒 System.out.println(Task A 结束 new Date()); } Scheduled(fixedRate 2000) // 每2秒执行一次 public void taskB() { System.out.println(Task B 执行 new Date()); } }输出结果可能如下Task A 开始10:00:00 Task A 结束10:00:03 Task B 执行10:00:03 // 延迟了1秒 Task A 开始10:00:04 // 延迟了2秒 ...3.3 配置任务优先级Spring 本身不直接支持任务优先级但可以通过以下方式间接控制方案一使用不同的线程池Configuration EnableScheduling public class PrioritySchedulingConfig implements SchedulingConfigurer { Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { // 高优先级任务线程池核心线程数多 ThreadPoolTaskScheduler highPriorityScheduler new ThreadPoolTaskScheduler(); highPriorityScheduler.setPoolSize(5); highPriorityScheduler.setThreadNamePrefix(high-priority-); highPriorityScheduler.initialize(); // 低优先级任务线程池核心线程数少 ThreadPoolTaskScheduler lowPriorityScheduler new ThreadPoolTaskScheduler(); lowPriorityScheduler.setPoolSize(2); lowPriorityScheduler.setThreadNamePrefix(low-priority-); lowPriorityScheduler.initialize(); // 注册任务到不同的调度器 taskRegistrar.setScheduler(highPriorityScheduler); // 默认使用高优先级 // 可以通过自定义注解或配置来指定任务使用的调度器 } }方案二使用 Order 注解有限效果Component Order(1) // 数字越小优先级越高 public class HighPriorityTask { Scheduled(fixedRate 1000) public void execute() { System.out.println(高优先级任务); } } Component Order(2) public class LowPriorityTask { Scheduled(fixedRate 1000) public void execute() { System.out.println(低优先级任务); } }注意Order主要影响 Bean 的加载顺序对任务执行顺序的影响有限。方案三手动控制执行顺序Component public class ManualPriorityTasks { private final Object lock new Object(); private boolean highPriorityRunning false; Scheduled(fixedRate 1000) public void highPriorityTask() { synchronized (lock) { highPriorityRunning true; try { System.out.println(高优先级任务执行); Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { highPriorityRunning false; } } } Scheduled(fixedRate 1000) public void lowPriorityTask() { synchronized (lock) { if (!highPriorityRunning) { System.out.println(低优先级任务执行); } } } }四、并行调度配置4.1 启用并行执行默认情况下Spring 使用单线程执行定时任务。要启用并行执行需要配置线程池Configuration EnableScheduling public class ConcurrentSchedulingConfig implements SchedulingConfigurer { Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { ThreadPoolTaskScheduler taskScheduler new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(10); // 设置线程池大小 taskScheduler.setThreadNamePrefix(scheduled-task-); taskScheduler.setAwaitTerminationSeconds(60); taskScheduler.setWaitForTasksToCompleteOnShutdown(true); taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); taskScheduler.initialize(); taskRegistrar.setTaskScheduler(taskScheduler); } }4.2 使用异步执行结合Async注解实现真正的异步并行Configuration EnableScheduling EnableAsync public class AsyncSchedulingConfig { Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.setThreadNamePrefix(scheduled-); return scheduler; } Bean public Executor asyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); executor.setThreadNamePrefix(async-); executor.initialize(); return executor; } } Component public class AsyncScheduledTasks { Async Scheduled(fixedRate 1000) public void asyncTask1() throws InterruptedException { System.out.println(Thread.currentThread().getName() - Task1 开始); Thread.sleep(2000); System.out.println(Thread.currentThread().getName() - Task1 结束); } Async Scheduled(fixedRate 1000) public void asyncTask2() { System.out.println(Thread.currentThread().getName() - Task2 执行); } }4.3 不同任务使用不同线程池Configuration EnableScheduling public class MultiThreadPoolConfig { Bean(ioTaskScheduler) public TaskScheduler ioTaskScheduler() { ThreadPoolTaskScheduler scheduler new ThreadPoolTaskScheduler(); scheduler.setPoolSize(5); scheduler.setThreadNamePrefix(io-scheduler-); scheduler.initialize(); return scheduler; } Bean(cpuTaskScheduler) public TaskScheduler cpuTaskScheduler() { ThreadPoolTaskScheduler scheduler new ThreadPoolTaskScheduler(); scheduler.setPoolSize(3); scheduler.setThreadNamePrefix(cpu-scheduler-); scheduler.initialize(); return scheduler; } } Component public class MultiPoolTasks { private final TaskScheduler ioScheduler; private final TaskScheduler cpuScheduler; public MultiPoolTasks( Qualifier(ioTaskScheduler) TaskScheduler ioScheduler, Qualifier(cpuTaskScheduler) TaskScheduler cpuScheduler) { this.ioScheduler ioScheduler; this.cpuScheduler cpuScheduler; // 手动调度IO密集型任务 ioScheduler.scheduleAtFixedRate(() - { System.out.println(IO任务执行 Thread.currentThread().getName()); }, Duration.ofSeconds(2)); // 手动调度CPU密集型任务 cpuScheduler.scheduleAtFixedRate(() - { System.out.println(CPU任务执行 Thread.currentThread().getName()); }, Duration.ofSeconds(3)); } }五、最佳实践与注意事项5.1 任务执行时间监控Component public class MonitoredScheduledTask { Scheduled(fixedRate 5000) public void monitoredTask() { long startTime System.currentTimeMillis(); try { // 业务逻辑 Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { long duration System.currentTimeMillis() - startTime; if (duration 3000) { System.err.println(任务执行超时 duration ms); } } } }5.2 避免任务阻塞设置合理的超时时间使用异步执行长时间任务避免在定时任务中进行同步IO操作考虑使用消息队列解耦5.3 集群环境下的定时任务在集群部署时需要防止同一任务在多个节点重复执行使用分布式锁Redis、ZooKeeper使用数据库乐观锁配置任务只在特定节点执行使用专门的调度中心如XXL-JOB、Elastic-Job5.4 动态修改 Cron 表达式Component public class DynamicScheduledTask { private final ScheduledTaskRegistrar registrar; private ScheduledFuture? future; public DynamicScheduledTask(ScheduledTaskRegistrar registrar) { this.registrar registrar; } public void scheduleTask(String cronExpression) { if (future ! null) { future.cancel(false); } TaskScheduler scheduler registrar.getScheduler(); future scheduler.schedule(() - { System.out.println(动态任务执行 new Date()); }, new CronTrigger(cronExpression)); } }六、总结Scheduled注解是 Spring 定时任务的核心通过合理使用 Cron 表达式、配置线程池和任务优先级可以构建出灵活可靠的定时任务系统。关键要点Cron 表达式掌握特殊字符和常用模式执行顺序默认单线程顺序执行可通过线程池实现并行优先级控制通过不同线程池或手动同步机制实现并行调度配置线程池大小结合Async实现真正异步生产实践监控任务执行时间避免阻塞集群环境需防重根据实际业务需求选择合适的调度策略平衡性能与可靠性才能构建出高效的定时任务系统。