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简介(新手必看)
ICP备案:
公安联网备案: