前言
定时任务是按照指定时间周期运行的短任务。
使用场景为在某个固定时间点,为所有运行中的节点做时间同步。
定时任务是基于时间控制的短时任务(Job),类似于Linux系统的crontab文件中的一行,在指定的时间周期运行指定的短时任务。在给定时间点只运行一次或在给定时间点周期性地运行。
在一些业务场景中,需要定时执行一些任务,例如:
- 定时推送一些接口数据,如每天 3 点向第三方系统发送当天的订单信息
- 定时派息、跑批对账、业务监控等,如每月 1 号凌晨 1 点执行银行卡的自动扣款
- 定时发起一个任务,如每周日,3 点 10 分发送问卷调查
- 定时清理一些过期或无用的数据,如每天 23 点删除当天的临时文件
快速使用
引入依赖
定时任务是 SpringBoot 框架中的基础内容,在引入 spring-boot-starter
时就包含了定时任务
org.springframework.boot
spring-boot-starter-web
开启定时任务
在 SpringBoot 启动类上添加注解 @EnableScheduling
即可开启
@EnableScheduling
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Cron 表达式
在线工具:Cron - 在线Cron表达式生成器 (ciding.cc)
Cron表达式是一种用于设置定时任务的语法规则
它由6个字段组成,分别表示秒、分、小时、日期、月份和星期几
每个字段都可以设置一个数字、一组数字(用逗号分隔)、一段数字范围(用短横线分隔)、通配符(表示任意值)或者特定的字符(如星期几的英文缩写)
以下是 cron 表达式的 6 个字段:
字段 | 允许值 | 允许的特殊字符 |
---|---|---|
秒 | 0~59 | , - * / |
分 | 0~59 | , - * / |
小时 | 0~23 | , - * / |
日 | 1~31 | , - * ? / L W C |
月份 | 1~12 | , - * / |
星期几 | 0~7 | , - * ? / L C # |
其中,特殊字符的含义如下:
*
:表示所有值。例如,*
在分钟字段中表示“每分钟”。?
:只能用在日和星期字段中,表示不指定值。当两个字段需要指定值时,其中一个可以使用?
。-
:表示一个范围。例如,在小时字段中使用10-12
表示“10点到12点”。,
:表示附加多个值。例如,在星期几字段中使用MON,WED,FRI
表示“周一、周三和周五”。/
:表示增量。例如,在秒钟字段中使用0/15
表示“0秒开始,每15秒执行一次”。L
:只能用在日和星期几字段中,表示“最后一天”。例如,在日字段中使用L
表示“每月最后一天”。W
:表示工作日(周一到周五)。例如,在日字段中使用15W
表示“离每月15号最近的工作日”。#
:表示第几个周几。例如,在星期几字段中使用6#3
表示“每月第三个周五”。
下面是一些常见的 cron 表达式例子:
- 每2秒执行任务:
*/2 * * * * ?
- 每2分钟执行任务:
0 */2 * * * ?
- 每天上午10:15执行任务:
0 15 10 ? * *
- 每月最后一天上午10:15执行任务:
0 15 10 L * ?
- 每周五上午10:15执行任务:
0 15 10 ? * FRI
使用
在方法上添加注解 @Scheduled
,定义 cron 表达式
@Service
public class ScheduleService {
// cron 秒 分 时 日 月 星期几
@Scheduled(cron = "00 00 23 * * *")
public void executeSchedule() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String currentDateTime = LocalDateTime.now().format(formatter);
// todo 定时任务业务逻辑
System.out.println("当前时间:" + currentDateTime + "执行了定时任务");
}
}
自定义线程池
@Configuration
public class CustomThreadPoolConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
// 设置线程池大小
scheduler.setPoolSize(10);
// todo 还可以设置其他线程池属性,比如如队列容量、线程名前缀等
return scheduler;
}
}