Spring 定时任务 SchedulingConfigurer 接口
在 Spring 中,创建简单的定时任务可以使用 @Scheduled 注解,但它有一个缺点,其定时的时间不能动态的改变,而使用基于 SchedulingConfigurer 接口的方式可以做到。
@Scheduled
/*
cron表达式语法:[秒] [分] [小时] [日] [月] [周] [年]
@Scheduled(fixedDelay = 5000) //上一次执行完毕时间点之后5秒再执行
@Scheduled(fixedDelayString = "5000") //上一次执行完毕时间点之后5秒再执行
@Scheduled(fixedRate = 5000) //上一次开始执行时间点之后5秒再执行
@Scheduled(initialDelay=1000, fixedRate=5000) //第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
*/
// 標記配置类
@Configuration
// 开启定時任務
@EnableScheduling
public class Schedule {
@Scheduled(cron = "0/5 * * * * ?")
private void configureTasks() {
System.err.println("基于注解(@Scheduled)的简单定时器demo: " + LocalDateTime.now());
}
}
SchedulingConfigurer
SchedulingConfigurer 接口可以实现在 @Configuration 类上,同时不要忘记需要 @EnableScheduling 注解。
该接口的实现方法如下:
public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
其中 ScheduledTaskRegistrar 类的方法有 Trigger 触发的任务、基于 Cron 表达式的任务、定时任务和延时任务。
以 TriggerTask 为例,示例如下:
@Configuration
@EnableScheduling
public class ConfigurerScheduling implements SchedulingConfigurer{
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
// 执行定时任务
() ->{
System.out.println("基于接口SchedulingConfigurer的动态定时任务:"
+ LocalDateTime.now()+",线程名称:"+Thread.currentThread().getName()
+ " 线程id:"+Thread.currentThread().getId());
},
// 设置触发器
triggerContext -> {
return new CronTrigger("0/5 * * * * ?").nextExecutionTime(triggerContext);
}
);
}
}
Thread
默认的,SchedulingConfigurer 使用的也是单线程的方式,如果需要配置多线程,则需要指定 PoolSize
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.initialize();
taskRegistrar.setTaskScheduler(taskScheduler);
// taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
taskRegistrar.addTriggerTask(...);
}
SpringBoot Demo
pom 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
yml 配置文件
#设置定时任务
task:
taskName1: #任务名称
switch: true #是否开启定時任務
cron: "0/5 * * * * ?" #任务表达式
taskName2:
switch: true
cron: "0/5 * * * * ?"
SchedulingConfigurer
@Configuration
@EnableScheduling
public abstract class ConfigurerSchedule implements SchedulingConfigurer{
private String cron;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
taskRegistrar.addTriggerTask(
// 执行定时任务
() ->{
processTask();
},
// 设置触发器
triggerContext -> {
if (StringUtils.isEmpty(cron)) {
cron = getCron();
}
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
/**
* @brief 任务的处理函数
* 本函数需要由派生类根据业务逻辑来实现
*/
protected abstract void processTask();
/**
* @return String
* @brief 获取定时任务周期表达式
* 本函数由派生类实现,从配置文件,数据库等方式获取参数值
*/
protected abstract String getCron();
}
TaskDemo
@Configuration
public class TaskDemo1 extends ConfigurerSchedule{
@Value(value = "${task.taskName1.switch}")
private Boolean isSwitch;
@Value(value = "${task.taskName1.cron}")
private String cron;
@Override
protected void processTask() {
if (isSwitch){
System.out.println("基于接口SchedulingConfigurer的动态定时任务:"
+ LocalDateTime.now()+",线程名称:"+Thread.currentThread().getName()
+ " 线程id:"+Thread.currentThread().getId());
}
}
@Override
protected String getCron() {
return cron;
}
}
@Configuration
public class TaskDemo2 extends ConfigurerSchedule{
@Value(value = "${task.taskName2.switch}")
private Boolean isSwitch;
@Value(value = "${task.taskName2.cron}")
private String cron;
@Override
protected void processTask() {
if (isSwitch) {
System.out.println("基于接口SchedulingConfigurer的动态定时任务:"
+ LocalDateTime.now() + ",线程名称:" + Thread.currentThread().getName()
+ " 线程id:" + Thread.currentThread().getId());
}
}
@Override
protected String getCron() {
return cron;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!