专栏名称: java一日一条
主要是讲解编程语言java,并且每天都推送一条关于java编程语言的信息
目录
相关文章推荐
Java编程精选  ·  字节员工自曝:再强调一遍OD ... ·  2 天前  
芋道源码  ·  SpringBoot CORS ... ·  2 天前  
芋道源码  ·  几个必会的JDK性能监控和故障处理工具 ·  4 天前  
芋道源码  ·  DeepSeek 全面指南:95% ... ·  4 天前  
芋道源码  ·  我司喜欢40岁程序员 ·  5 天前  
51好读  ›  专栏  ›  java一日一条

springBoot中@Scheduled执行原理解析

java一日一条  · 公众号  · Java  · 2019-09-16 19:27

正文

前言

本文主要介绍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)。

重要代码如下:

//说明:ScheduledAnnotationBeanPostProcessor继承BeanPostProcessor。@Overridepublic Object postProcessAfterInitialization(final Object bean, String beanName) {          //省略多个判断条件代码         for (Map.EntrySet> 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());






请到「今天看啥」查看全文