当前位置: 代码迷 >> 综合 >> @Scheduled 注解调度器深入解读
  详细解决方案

@Scheduled 注解调度器深入解读

热度:21   发布时间:2023-12-08 12:43:03.0

文章目录

        • 一、场景及背景描述
        • 二、@Scheduled 注解调度器的实现
        • 三、@Scheduled 注解任务调度详细说明
          • 1、Cron 表达式的使用方式
          • 2、fixedDelay & fixedDelayString 的使用方式
          • 3、fixedRate & fixedRateString 的使用方式
          • 4、initialDelay & initialDelayString 的使用方式

一、场景及背景描述
  • 在项目开发过程中,我们经常需要执行具有固定周期性的任务,比如:会员到期提醒机制、手机话费停机提醒机制等。通过定时任务可以很好的帮助我们实现这些背景的功能。

  • 常见几种定时任务比较:

    定时任务框架 Cron 表达式 固定间隔执行 固定频率执行 任务持久化 开发难易度
    JDK TimerTask 不支持 支持 支持 不支持 简单
    Spring Schedule 支持 支持 支持 不支持 一般
    Quartz 支持 支持 支持 支持 复杂

    后续文章将会给出以上所有定时器的实现方式

二、@Scheduled 注解调度器的实现
  1. 添加 Spring Boot 依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
    </dependencies>
    
  2. 应用主启动类添加 @EnableScheduling 注解

    /*** Copyright (C), 1998-2021, Shenzhen Rambo Technology Co., Ltd* Spring Boot Scheduled Sample 演示启动类** @author Rambo* @date 2021/02/19 17:06* @since 1.0.0.1*/
    @SpringBootApplication
    @EnableScheduling
    public class SpringBootScheduleSampleApplication {
          public static void main(String[] args) {
          SpringApplication.run(SpringBootScheduleSampleApplication.class, args);}
    }
    
  3. 在需要实现调度任务的方法上添加 @Scheduled 注解并设置相应的调度周期即可

  4. @Scheduled 注解所支持的参数

    参数属性 属性描述
    cron cron表达式,指定任务在特定时间执行
    fixedDelay 表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms
    fixedDelayString 与fixedDelay含义一样,只是参数类型变为String
    fixedRate 表示按一定的频率执行任务,参数类型为long,单位ms
    fixedRateString 与fixedRate的含义一样,只是将参数类型变为String
    initialDelay 表示延迟多久再第一次执行任务,参数类型为long,单位ms
    initialDelayString 与initialDelay的含义一样,只是将参数类型变为String
    zone 时区,默认为当前时区,一般没有用到
三、@Scheduled 注解任务调度详细说明
1、Cron 表达式的使用方式
  • 指定任务在特定时间执行
  1. 表达式定义规则

    Cron 表达式由 6 或 7 个空格分隔的时间字段组成

    位置 时间域名 允许值 允许的特殊字符
    1 秒钟 0~59 , - * /
    2 分钟 0~59 , - * /
    3 小时 0~23 , - * /
    4 日期 1~31 , - * ? / L W C
    5 月份 1~12 , - * /
    6 星期 1~7 , - * ? / L C #
    7 年(可选) 空值 1970~2099 , - * /
  2. 常用表达式

    表达式 功能描述
    0/30 * * * * * 每30秒执行一次
    0 0/5 * * * * 每5分钟执行一次
    0 0 0 * * * 每天凌晨执行一次
    0 0 9,12,18 * * * 每天9点、12点、18点整执行一次
    0 30 3-5 * * * 每天 3~5点 30分执行一次
  3. 添加一个 cronTest 方法,并且设置每5秒执行一次,并且每次执行耗时10秒

    /*** 使用 @Scheduled 注解的前提:在启动类开启了 @EnableScheduling 注解** @author Rambo* @date 2021/2/20 09:55*/
    @Scheduled(cron = "0/5 * * * * ?")
    public void cronTest() throws InterruptedException {
          log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.cronTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10);
    }
    
  4. 当方法执行时间超过任务调度频率,调度器会在(耗时 + 调度频率)后执行,即:第一次调度任务开始到任务结束以后(无论耗时多长)这一刻开始,再重新开始计时频率

    1

2、fixedDelay & fixedDelayString 的使用方式
  • 表示上一次任务执行完成后多久再次执行
  1. 添加一个 fixedDelayTest 方法,每隔5秒执行一次,每次耗时10秒

    // @Scheduled(fixedDelay = 1000*5)
    @Scheduled(fixedDelayString = "5000")
    public void fixedDelayTest() throws InterruptedException {
          log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.fixedDelayTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10);
    }
    
  2. 当执行频率小于执行耗时都场景,下一次调度的时间是 (耗时 + 调度频率)的时间

    2

3、fixedRate & fixedRateString 的使用方式
  • 表示按一定的频率执行任务
  1. 添加一个 fixedRateTest 方法,每隔5秒执行一次,每次耗时10秒

    // @Scheduled(fixedRate = 1000*5)
    @Scheduled(fixedRateString = "50000")
    public void fixedRateTest() throws InterruptedException {
          log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.fixedRateTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10);
    }
    
  2. 效果说明

    • 如果执行频率大于执行耗时,则按照执行频率定时调度

    • 如果执行频率小于执行耗时,则下一次执行调度会在执行耗时以后立刻执行

    3

4、initialDelay & initialDelayString 的使用方式
  • 表示延迟多久再第一次执行任务
  1. 添加一个 initialDelayTest 方法,每隔5秒执行一次,每次耗时10秒

     // @Scheduled(initialDelay = 10000, fixedDelay = 5000)
    @Scheduled(initialDelayString = "10000", fixedDelay = 5000)
    public void initialDelayTest() throws InterruptedException {
          log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.initialDelayTest()],首次运行等待10秒后执行调度任务,后续频率5秒/次,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10);
    }
    

    P.S

    initialDelayinitialDelayString 必须和非 cron 表达式都其它两组组合使用

  2. 效果说明

    • initialDelayinitialDelayString 必须和非 cron 表达式都其它两组组合使用
    • 首次执行按照 initialDelayinitialDelayString 预设值延迟后,后续所有频率按照其它组合都特性进行
  相关解决方案