@Scheduled
注解是 Spring Framework 提供的一个非常方便的定时任务执行功能,它使得开发者无需编写复杂的定时任务代码,只需在方法上添加该注解并配置相应的执行计划,Spring 就会根据配置自动执行该方法。
1. 基本使用
首先,你需要在 Spring Boot 的主配置类(通常是带有 @SpringBootApplication
注解的类)上添加 @EnableScheduling
注解,以启用定时任务的支持。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
然后,你可以在任意 Spring 管理的 bean 上使用 @Scheduled
注解来定义定时任务。
2. 注解属性
@Scheduled
注解有几个重要的属性:
fixedRate
:上一次任务执行完成后开始计算,直到下一次任务开始执行的间隔时间,单位为毫秒。fixedDelay
:上一次任务执行完成后开始计算,直到下一次任务开始执行的延迟时间,单位为毫秒。initialDelay
:首次执行任务之前的延迟时间,单位为毫秒。cron
:基于 cron 表达式的定时任务执行计划。
3. 示例代码
在任何Spring管理的bean上使用@Scheduled注解来定义定时任务。
固定速率执行任务
下面的示例中,任务将每隔 5 秒执行一次。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyScheduledTasks {
@Scheduled(fixedRate = 5000) // 每隔 5 秒执行一次
public void doSomething() {
// 执行任务的代码
System.out.println("执行定时任务: " + new Date());
}
}
Cron 表达式执行任务
下面的示例中,任务将在每天的上午 10 点执行。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyScheduledTasks {
@Scheduled(cron = "0 0 10 * * ?") // 每天上午 10 点执行
public void doSomethingAtTenAm() {
// 执行任务的代码
System.out.println("上午 10 点执行定时任务: " + new Date());
}
}
Cron表达式是一种强大的工具,用于定义定时任务的执行计划。下面是一些Cron表达式的各种示例,以展示其灵活性和功能:
每X分钟执行一次
如果你想要每5分钟执行一次任务,你可以这样写:
0 0/5 * * * ?
每小时的特定分钟执行
假设你希望每小时的第15分钟执行任务,你可以这样配置:
0 15 * * * ?
每天特定时间执行
如果你想要每天中午12点执行任务,Cron表达式如下:
0 0 12 * * ?
或者,如果你想要每天下午3点30分执行任务:
0 30 15 * * ?
每天多次执行
假设你希望每天上午9点,中午12点和下午5点执行任务:
0 0 9,12,17 * * ?
每周特定时间执行
每周日早上8点执行任务:
0 0 8 ? * SUN
或者,每周一到周五的下午4点执行任务:
0 0 16 ? * MON-FRI
每月特定日期执行
每月的第一天凌晨1点执行任务:
0 0 1 1 * ?
或者,每月的最后一个工作日(周五)的下午5点执行任务:
0 0 17 LW * ?
这里的LW
表示该月的最后一个工作日。
每X月的特定日期执行
每年的3月、6月、9月和12月的第10天的上午10点执行任务:
0 0 10 10 3,6,9,12 ?
每年特定日期执行
每年的1月1日凌晨0点执行任务:
0 0 0 1 1 ?
每隔X小时执行
每隔3小时执行一次任务:
0 0/3 * * * ?
组合使用
你还可以组合使用日期和星期的字段。例如,下面的Cron表达式表示“每个月的1号和15号的上午10点,以及每个周三的上午10点”执行任务:
0 0 10 1,15 * ?
0 0 10 * * WED
注意,当日期和星期字段都设置了值时,Cron表达式采用的是“或”的逻辑,即只要满足其中一个条件就会执行任务。
排除特定日期
如果你想在每月的每一天都执行任务,除了特定的几天,你可以使用!
来排除这些日期。例如,下面的Cron表达式表示“每月的每一天都执行,除了13号”:
0 0 0 * * ? L-13
这里L
表示月的最后一天,L-13
则表示倒数第13天,也就是13号。
这些示例展示了Cron表达式的多样性和灵活性,你可以根据自己的需求来定制任务的执行计划。当然,在实际应用中,还需要注意Cron表达式中各个字段的允许值和特殊字符的使用。
4. 注意事项
- 确保你的任务方法是无状态的,因为多个线程可能会同时执行它。
- 如果你的任务执行时间较长,并且你使用了
fixedRate
,那么可能会在下一个任务开始执行时,上一个任务还未完成,这可能会导致问题。在这种情况下,你可能需要考虑使用fixedDelay
或其他机制。 - 对于需要精确执行时间的任务,建议使用数据库或其他持久化存储来记录任务的执行状态和时间,以防止在应用程序重启或崩溃时丢失任务。