文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

@Scheduled fixedDelayString 加载properties配置方式

2024-04-02 19:55

关注

@Scheduled fixedDelayString 加载properties配置


@Component
public class ScheduledServiceImpl {
    @Scheduled(fixedDelayString = "${eventTracking.delayFixed}")
    private void doTask() {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        System.out.println("current time >>> " + timestamp.toString());
    }
}
 

@Scheduled执行原理解析

一:前言

本文主要介绍Spring Boot中使用定时任务的执行原理。

二:@Scheduled使用方式

定时任务注解为@Scheduled。使用方式举例如下:


//定义一个按时间执行的定时任务,在每天16:00执行一次。
@Scheduled(cron = "0 0 16 * * ?")
public void depositJob() {
  //执行代码
}
//定义一个按一定频率执行的定时任务,每隔1分钟执行一次
    @Scheduled(fixedRate = 1000 * 60)
    public void job2() {
    //执行代码
}
//定义一个按一定频率执行的定时任务,每隔1分钟执行一次,延迟1秒执行
    @Scheduled(fixedRate = 1000 * 60,initialDelay = 1000)
    public void updatePayRecords() {
    //执行代码
}

备注:具体参数可以参考“spring-context-4.2.4.RELEASE.jar”下面的“org.springframework.scheduling.annotation.Scheduled"类。

三:@Scheduled代码执行原理说明

简要介绍:spring在初始化bean后,通过“postProcessAfterInitialization”拦截到所有的用到“@Scheduled”注解的方法,并解析相应的的注解参数,放入“定时任务列表”等待后续处理;之后再“定时任务列表”中统一执行相应的定时任务(任务为顺序执行,先执行cron,之后再执行fixedRate)。

重要代码如下:

第一步:依次加载所有的实现Scheduled注解的类方法。


//说明:ScheduledAnnotationBeanPostProcessor继承BeanPostProcessor。
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) {
          //省略多个判断条件代码
         for (Map.Entry<Method, Set<Scheduled>> entry : annotatedMethods.entrySet()) {
            Method method = entry.getKey();
            for (Scheduled scheduled : entry.getValue()) {
               processScheduled(scheduled, method, bean);
            }
         }
   }
   return bean;
}

第二步:将对应类型的定时器放入相应的“定时任务列表”中。


//说明:ScheduledAnnotationBeanPostProcessor继承BeanPostProcessor。
//获取scheduled类参数,之后根据参数类型、相应的延时时间、对应的时区放入不同的任务列表中
protected void processScheduled(Scheduled scheduled, Method method, Object bean) {   
     //获取corn类型
      String cron = scheduled.cron();
      if (StringUtils.hasText(cron)) {
         Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");
         processedSchedule = true;
         String zone = scheduled.zone();
         //放入cron任务列表中(不执行)
         this.registrar.addCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone)));
      }
      //执行频率类型(long类型)
      long fixedRate = scheduled.fixedRate();
      String fixedDelayString = scheduled.fixedDelayString();
      if (fixedRate >= 0) {
         Assert.isTrue(!processedSchedule, errorMessage);
         processedSchedule = true;
          //放入FixedRate任务列表中(不执行)(registrar为ScheduledTaskRegistrar)
         this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
      }
     //执行频率类型(字符串类型,不接收参数计算如:600*20)
      String fixedRateString = scheduled.fixedRateString();
      if (StringUtils.hasText(fixedRateString)) {
         Assert.isTrue(!processedSchedule, errorMessage);
         processedSchedule = true;
         if (this.embeddedValueResolver != null) {
            fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);
         }
         fixedRate = Long.parseLong(fixedRateString);
         //放入FixedRate任务列表中(不执行)
         this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
      }
}
   return bean;
}

第三步:执行相应的定时任务。

说明:定时任务先执行corn,判断定时任务的执行时间,计算出相应的下次执行时间,放入线程中,到相应的时间后进行执行。之后执行按“频率”(fixedRate)执行的定时任务,直到所有任务执行结束。


protected void scheduleTasks() {
   //顺序执行相应的Cron
   if (this.cronTasks != null) {
      for (CronTask task : this.cronTasks) {
         this.scheduledFutures.add(this.taskScheduler.schedule(
               task.getRunnable(), task.getTrigger()));
      }
   }
  //顺序执行所有的“fixedRate”定时任务(无延迟,也就是说initialDelay参数为空),因为无延迟,所以定时任务会直接执行一次,执行任务完成后,会将下次执行任务的时间放入delayedExecute中等待下次执行。
   if (this.fixedRateTasks != null) {
      for (IntervalTask task : this.fixedRateTasks) {
         if (task.getInitialDelay() > 0) {
            Date startTime = new Date(now + task.getInitialDelay());
            this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
                  task.getRunnable(), startTime, task.getInterval()));
         }
         else {
            this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
                  task.getRunnable(), task.getInterval()));
         }
      }
   }
//顺序执行所有的“fixedRate”定时任务(有延迟,也就是说initialDelay参数不为空)
   if (this.fixedDelayTasks != null) {
      for (IntervalTask task : this.fixedDelayTasks) {
         if (task.getInitialDelay() > 0) {
            Date startTime = new Date(now + task.getInitialDelay());
            this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
                  task.getRunnable(), startTime, task.getInterval()));
         }
         else {
            this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
                  task.getRunnable(), task.getInterval()));
         }
      }
   }
}

接下来看下定时任务run(extends自Runnable接口)方法:


//说明:每次执行定时任务结束后,会先设置下下次定时任务的执行时间,以此来确认下次任务的执行时间。
public void run() {
    boolean periodic = isPeriodic();
    if (!canRunInCurrentRunState(periodic))
        cancel(false);
    else if (!periodic)
        ScheduledFutureTask.super.run();
    else if (ScheduledFutureTask.super.runAndReset()) {
        setNextRunTime();
        reExecutePeriodic(outerTask);
    }
}

备注1:从上面的代码可以看出,如果多个定时任务定义的是同一个时间,那么也是顺序执行的,会根据程序加载Scheduled方法的先后来执行。

但是如果某个定时任务执行未完成会出现什么现象呢?

答:此任务一直无法执行完成,无法设置下次任务执行时间,之后会导致此任务后面的所有定时任务无法继续执行,也就会出现所有的定时任务“失效”现象。

所以应用springBoot中定时任务的方法中,一定不要出现“死循环”、“http持续等待无响应”现象,否则会导致定时任务程序无法正常。再就是非特殊需求情况下可以把定时任务“分散”下。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯