一、定时器概述
Spring Boot 提供了简单易用的定时任务功能,可以方便地实现周期性任务的执行。本教程将详细介绍如何在 Spring Boot 项目中配置和使用定时器。
二、环境准备
Spring Boot 项目本身已经集成了定时任务功能,不需要额外引入依赖包。只需确保你的项目是基于 Spring Boot 构建的即可。
三、启用定时任务
1. 主启动类配置
在 Spring Boot 的主启动类上添加 @EnableScheduling
注解,这是启用定时任务的核心注解:
@SpringBootApplication
@EnableScheduling // 启用定时任务功能
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
四、创建定时任务
1. 定时任务类定义
创建一个普通的 Java 类,并使用 @Component
注解将其声明为 Spring 组件:
@Component
public class ScheduledTasks {
// 定时任务方法将在这里定义
}
五、定时任务配置方式
Spring Boot 提供了多种方式来配置定时任务的执行时间:
1. Cron 表达式方式(最灵活)
使用 @Scheduled(cron = "表达式")
注解,可以非常灵活地定义任务执行时间。
常用 Cron 表达式示例:
0 0 8 * * ?
- 每天上午8点执行0 0/5 14 * * ?
- 每天下午2点到2:55期间,每5分钟执行一次0 15 10 ? * MON-FRI
- 周一至周五的上午10:15执行0 0 12 * * ?
- 每天中午12点执行0 0 3 * * ?
- 每天凌晨3点执行0 0/30 9-17 * * MON-FRI
- 工作日9:00-17:30每半小时执行一次0 15 10 L * ?
- 每月最后一天10:15执行0 0 12 ? * WED
- 每周三中午12点执行
Cron 表达式字段说明:
字段 | 允许值 | 特殊符号 |
---|---|---|
秒 | 0-59 | , - * / |
分 | 0-59 | , - * / |
时 | 0-23 | , - * / |
日 | 1-31 | , - * ? / L W C |
月 | 1-12 或 JAN-DEC | , - * / |
周 | 1-7 或 SUN-SAT | , - * ? / L C # |
年 | 可选 1970-2099 | , - * / |
特殊符号说明:
*
: 所有值?
: 不指定(日/周冲突时使用)-
: 范围(如9-17)/
: 间隔(0/15每15秒)L
: 最后(日:月末;周:周六)W
: 最近工作日#
: 第几个周几(6#3:每月第3个周五)
2. 固定速率方式 (fixedRate)
使用 @Scheduled(fixedRate = 时间毫秒数)
注解,任务以固定的频率执行,不考虑上次任务的执行时间。
@Scheduled(fixedRate = 5000) // 每5秒执行一次
public void reportCurrentTime() {
System.out.println("定时任务执行: " + new Date());
}
特性:
- 始终按固定频率执行
- 不等待上次任务完成
- 适用于独立任务(无状态)
3. 固定延迟方式 (fixedDelay)
使用 @Scheduled(fixedDelay = 时间毫秒数)
注解,任务在上次执行完成后,延迟指定时间再执行下一次。
@Scheduled(fixedDelay = 3000) // 上次执行结束后3秒执行
public void fixedDelayTask() {
// 模拟耗时任务
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
特性:
- 严格保证任务间隔(含执行时间)
- 适用于有先后依赖的任务
4. 初始延迟方式 (initialDelay)
结合 fixedRate
或 fixedDelay
使用,可以设置任务首次执行的延迟时间。
@Scheduled(initialDelay = 10000, fixedRate = 15000) // 容器启动后延迟10秒,之后每15秒执行一次
public void test() {
System.out.println("定时任务执行");
}
六、多线程定时任务
默认情况下,Spring Boot 的定时任务是单线程执行的。如果有多个定时任务,它们会按顺序执行。如果需要多线程执行定时任务,可以配置一个 TaskScheduler
:
@Configuration
public class TaskSchedulerConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5); // 设置线程池大小
scheduler.setThreadNamePrefix("scheduled-task-");
return scheduler;
}
}
七、实际应用示例
1. 每5秒执行一次的任务
@Component
public class FixedRateTask {
@Scheduled(fixedRate = 5000) // 每5秒执行一次
public void performTask() {
System.out.println("固定间隔任务执行,当前时间:" + System.currentTimeMillis());
}
}
2. 每天凌晨3点执行的任务
@Component
public class DailyTask {
@Scheduled(cron = "0 0 3 * * ?") // 每天凌晨3点执行
public void dailyTask() {
System.out.println("每日任务执行: " + new Date());
// 这里可以添加具体的业务逻辑
}
}
3. 工作日每半小时执行一次的任务
@Component
public class WorkdayTask {
@Scheduled(cron = "0 0/30 9-17 * * MON-FRI") // 工作日9:00-17:30每半小时执行一次
public void workdayTask() {
System.out.println("工作日定时任务执行: " + new Date());
}
}
八、注意事项
-
时区问题:默认情况下,Cron 表达式使用服务器的时区。如果需要指定时区,可以使用
zone
属性:@Scheduled(cron = "0 0 3 * * ?", zone = "Asia/Shanghai")
-
任务执行时间:如果任务执行时间超过调度间隔,可能会导致任务重叠。对于这种情况,可以考虑使用
fixedDelay
或增加线程池大小。 -
异常处理:定时任务中的异常不会影响其他任务的执行,但建议在任务方法内部做好异常处理。
-
日志记录:建议为定时任务添加适当的日志记录,便于监控和问题排查。
九、总结
Spring Boot 的定时任务功能简单易用,通过 @EnableScheduling
和 @Scheduled
注解可以轻松实现各种定时任务需求。根据业务场景选择合适的调度方式(Cron 表达式、固定速率或固定延迟),并注意多线程配置和异常处理,可以构建出稳定可靠的定时任务系统。