SpringBoot @Scheduled定时任务详解(附带实例)
在日常的项目开发中,往往会需要后台定时执行某项任务,比如自动将超过 24 小时的未付款订单改为取消状态,自动将超过 14 天客户未签收的订单改为已签收状态等。
如何在 Spring Boot 中实现后台定时任务的功能呢?本节将介绍使用 Spring Boot 内置的 @Scheduled 注解来实现定时任务。
下面演示使用 @Scheduled 注解实现定时任务:
@Scheduled 不仅支持以 Cron 表达式的方式定义执行周期,还支持以固定时间间隔的方式调度任务。下面定义一个固定时间间隔执行的任务,具体的代码如下:

图 1 后台定时任务执行日志
后台日志显示,SchedulerTask 任务每隔 10 秒输出当前时间,说明定义的任务正在后台定时执行。
同时,@Scheduled 还支持简单的延时操作,比如 fixedDelay、initialDelay 后面填写相应的毫秒数即可:
总的来说,fixedRate 简单易懂,而 Cron 表达式功能灵活,支持定义复杂的时间规则。二者各有优劣,使用时可根据实际的业务需求选择。
如果只有一个定时任务,这样做肯定没问题;当定时任务增多时,如果一个任务被阻塞,则会导致其他任务无法正常执行。要解决这个问题,需要配置任务调度线程池。

图 2 后台定时任务执行日志
通过后台日志可以看到,Spring Boot 启动线程池负责调度执行后台任务,各个后台任务之间相对独立、互不影响。
如何在 Spring Boot 中实现后台定时任务的功能呢?本节将介绍使用 Spring Boot 内置的 @Scheduled 注解来实现定时任务。
@Scheduled注解实现定时任务
Spring Boot 提供了内置的 @Scheduled 注解实现定时任务的功能。使用 @Scheduled 注解创建定时任务非常简单,只需几行代码即可完成。下面演示使用 @Scheduled 注解实现定时任务:
1) 修改启动类
在启动类上加上 @EnableScheduling 开启定时任务,具体的代码如下:@SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }在上面的示例中,使用 @EnableScheduling 注解打开定时功能之后,默认情况下,系统会自动启动一个线程,调度执行定义的后台定时任务。
2) 创建定时任务类
首先创建 SchedulerTask 类,然后在任务方法上添加 @Scheduled 注解,具体的代码如下:@Component public class SchedulerTask { private static final Logger logger = LoggerFactory.getLogger(SchedulerTask.class); @Scheduled(cron="*/10 * * * * ?") private void taskCron(){ SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); logger.info("现在时间Scheduled1: " + dateFormat.format(new Date())); } }在上面的示例中,创建了 taskCron 的定时任务,然后在 taskCron() 方法中增加了 @Scheduled 注解设置 Cron 表达式,设置任务每隔 10 秒执行一次。
@Scheduled 不仅支持以 Cron 表达式的方式定义执行周期,还支持以固定时间间隔的方式调度任务。下面定义一个固定时间间隔执行的任务,具体的代码如下:
@Scheduled(fixedRate = 10000) public void taskFixed() { SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); logger.info("现在时间Scheduled2: " + dateFormat.format(new Date())); }在上面的示例中,使用 fixedRate 参数就是指固定的时间间隔,单位是毫秒,即设置任务每隔 10 秒执行一次。
3) 启动项目
创建好 SchedulerTask 定时任务后启动项目,查看后台任务的运行情况,如下图所示:
图 1 后台定时任务执行日志
后台日志显示,SchedulerTask 任务每隔 10 秒输出当前时间,说明定义的任务正在后台定时执行。
@Scheduled时间参数设置
@Scheduled 注解可以接受两种定时的参数设置:- 一种是我们常用的 cron 参数,设定按 Cron 表达式方式执行,比如 @Scheduled(cron="*/5 * * * * *") 为间隔 5 秒执行。
- 另一种是按 fixedRate 设定的固定时间执行,单位为毫秒,如 @Scheduled(fixedDelay =5000) 为上一次执行完毕时间点之后 5 秒再次执行,每次执行间隔 5 秒。
同时,@Scheduled 还支持简单的延时操作,比如 fixedDelay、initialDelay 后面填写相应的毫秒数即可:
- @Scheduled(fixedDelay =10000):上一次执行完毕时间点之后 10 秒再执行;
- @Scheduled(initialDelay=1000, fixedRate=10000):首次延迟 1 秒后执行,之后按 fixedRate 指定的固定时间间隔执行,即每 10 秒执行一次。
总的来说,fixedRate 简单易懂,而 Cron 表达式功能灵活,支持定义复杂的时间规则。二者各有优劣,使用时可根据实际的业务需求选择。
多线程定时任务
默认情况下,Spring Boot 定时任务是按单线程方式执行的,也就是说,如果同一时刻有两个定时任务需要执行,那么只能在一个定时任务完成之后再执行下一个。如果只有一个定时任务,这样做肯定没问题;当定时任务增多时,如果一个任务被阻塞,则会导致其他任务无法正常执行。要解决这个问题,需要配置任务调度线程池。
1) 增加多线程配置类
在 config 目录下增加 SchedulerConfig 配置类,代码如下:public class SchedulerConfig { @Bean public Executor taskScheduler() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(3); executor.setMaxPoolSize(10); executor.setQueueCapacity(3); executor.initialize(); return executor; } }设置执行线程池为 3,最大线程数为 10。
2) 修改SchedulerTask定时任务
修改之前定义的 SchedulerTask 定时任务的类,在方法上增加 @Async 注解,使得后台任务能够异步执行,代码如下:@EnableAsync // 开启异步事件的支持 @Component public class SchedulerTask { private static final Logger logger = LoggerFactory.getLogger(SchedulerTask.class); @Async @Scheduled(cron="*/10 * * * * ?") public void taskCron() { SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); logger.info("SchedulerTask taskCron 现在时间: " + dateFormat.format(new Date())); } @Async @Scheduled(fixedRate = 5000) public void taskFixed() { SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); logger.info("SchedulerTask taskFixed 现在时间: " + dateFormat.format(new Date())); } }在上面的示例中,定时任务类 SechedulerTask 增加了 @EnableAsync 注解,开启了异步事件支持。同时,在定时方法上增加 @Async 注解,使任务能够异步执行,这样各个后台任务就不会阻塞。
3) 启动项目
配置修改完成后,重新启动项目,查看后台任务的运行情况。如下图所示,全部的后台任务分成了多个线程执行,这样任务之间不会相互影响。
图 2 后台定时任务执行日志
通过后台日志可以看到,Spring Boot 启动线程池负责调度执行后台任务,各个后台任务之间相对独立、互不影响。
相关文章
- SpringBoot @Scheduled实现定时任务(附带实例)
- SpringBoot是什么?SpringBoot的优缺点有哪些?
- SpringBoot URL映射详解(附带实例)
- SpringBoot @PathVariable实现参数传递(附带实例)
- SpringBoot传递参数的5种方法(附带实例)
- SpringBoot Cron表达式的用法(新手必看)
- SpringBoot集成Redis详解(附带实例)
- SpringBoot集成RabbitMQ详解(附带实例)
- SpringBoot实现RabbitMQ简单队列(附带实例)
- SpringBoot是什么,SpringBoot简介(新手必看)