实现1、通过开启@EnableScheduling 及注解@Scheduled 实现定时执行任务,【在启动后无法修改定时执行周期】
【完整示例】
package org.javatrip.springboottimer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@EnableScheduling
public class ScheduledTasks {
// @Scheduled(cron = "*/50 * * * * ?") // 每小时执行一次
@Scheduled(fixedRate = 50000, initialDelay = 5000,fixedDelay = 5000)
public void executeEveryHour() {
System.out.println("定时器被触发: " + new Date());
}
}
有两种方式为不同场景【在启动后无法修改定时执行周期】
- 配置Cron表达式,@Scheduled(cron = “* */50 * * * ?”)
建议:直接点击在线Cron表达式生成器生成参数比较方便:https://www.matools.com/cron/
**【注意】**Cron表达式的开始执行时机,为表达式对应的,系统执行时间所对应的cron表达式时间,
如:每5分钟执行一次,当前系统时间为 10:03分,则定时器开始执行为 10:05执行
- 固定频率执行@Scheduled(fixedRate = 50000, initialDelay = 5000,fixedDelay = 5000)
该方式可以设置在系统启动后立即执行,也可延迟执行
实现2、通过开启@EnableScheduling及实现接口 SchedulingConfigurer 完成定时执行任务【在启动后无法修改定时执行周期】
完整示例
package org.javatrip.springboottimer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
@EnableScheduling
@Configuration
public class QuartzSchedulerTask implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 设置可变定时器
String cors = "0/5 * * * * ?";
// 注册方式1
taskRegistrar.addCronTask(() -> {System.out.println("SchedulingConfigurer cron task");}, cors);
// 注册方式2
taskRegistrar.addCronTask(new Runnable() {
@Override
public void run() {
System.out.println("SchedulingConfigurer cron task");
}
}, cors);
// 注册方式3,可实现动态修改
taskRegistrar.addTriggerTask(() -> {
System.out.println("SchedulingConfigurer cron task" + LocalDateTime.now().toString());
}, triggerContext -> {
System.out.println("=====SchedulingConfigurer cron task");
// return new CronTrigger(cors).nextExecutionTime(triggerContext).toInstant();
return new PeriodicTrigger(5000).nextExecutionTime(triggerContext).toInstant();
}
);
}
}
这个使用场景主要可以实现创建多种不同的定时器
注册不同的定时器
**【注意】**实现1、实现2都是只能创建一次性的固定定时器。注册方式3中可实现动态修改
实现3、通过配置@Bean 的TaskScheduler 并采用任务线程池的方式实现多线程任务定时器【可以动态修改定时器执行周期(先删除再新增方式)】
完整示例
创建配置类
package org.javatrip.springboottimer.threadpool;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.setThreadNamePrefix("task-scheduler-");
return taskScheduler;
}
}
创建业务定时器
package org.javatrip.springboottimer.threadpool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.ScheduledFuture;
@Component
public class MyDynamicTask {
@Autowired
private TaskScheduler taskScheduler;
private ScheduledFuture<?> scheduledFuture;
// 固定的时间间隔执行
public static void startTask_FixedRate_period(long interval) {
if (scheduledFuture != null){
scheduledFuture = taskScheduler.scheduleAtFixedRate(() -> {
System.out.println("run task FixedRate" + LocalDateTime.now().toString());
}, Duration.ofSeconds(5));
}
}
// 指定时间开始固定间间隔执行
public void startTask_FixedRate_Duration(long interval) {
if (scheduledFuture != null){
scheduledFuture = taskScheduler.scheduleAtFixedRate(() -> {
System.out.println("run task FixedRate" + LocalDateTime.now().toString());
},LocalDateTime.now().toInstant(ZoneOffset.of("+8")), Duration.ofSeconds(5));
}
}
// 固定的时间点执行
public void startTask_Instance(long interval) {
if (scheduledFuture != null){
scheduledFuture = taskScheduler.schedule(() -> {
System.out.println("run task FixedRate" + LocalDateTime.now().toString());
}, LocalDateTime.now().toInstant(ZoneOffset.of("+8")) );
}
}
// 创建周期Cron定时器
public void startTask_CronTrigger() {
if (scheduledFuture != null){
scheduledFuture = taskScheduler.schedule(() -> {
System.out.println("run task FixedRate" + LocalDateTime.now().toString());
}, new CronTrigger("0/5 0 * * * ?"));
}
}
// 创建固定周期定时器
public void startTask_PeriodicTrigger(long interval) {
if (scheduledFuture != null){
scheduledFuture = taskScheduler.schedule(() -> {
System.out.println("run task FixedRate" + LocalDateTime.now().toString());
}, new PeriodicTrigger(interval));
}
}
// 停止删除定时器
public void stopTask() {
if (scheduledFuture != null){
scheduledFuture.cancel(true);
}
}
}
业务使用定时器
在需要的方法中执行 MyDynamicTask.startTask的开启方法,进行开启一个定时器。
当停止定时器时可以通过调用 MyDynamicTask.stopTask.
当需要修改时,1、先调用 MyDynamicTask.stopTask.停止之前的 2、再 MyDynamicTask.startTask的开启新的
**【注意】**该示例中TaskScheduler 采用的是ThreadPoolTaskScheduler 线程池的方式,这样有利于处理高并发场景下的多任务定时器。
同时TaskScheduler接口 还有其他不同的实现类,可以在不同的场景下使用。