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;
  }
}
posted @   懦尘  阅读(1598)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示