• @Scheduled定时器


    一、基本使用

    @Scheduled  // 由Spring定义,用于将方法设置为调度任务。如:定时执行一次或定时轮询执行一段代码。该注解放到需要定时执行的方式上
    
    @EnableScheduling  // 再项目启动类上添加注解@EnableScheduling,表示开启定时任务
    
    • 1
    • 2
    • 3
    @Scheduled(fixedDelay=20*1000)   //每隔20秒执行
    public void scheduledTaskByFixedDelay() {
        log.info("定时任务开始 ByFixedDelay:" + DateUtils.getDatetimeString());
        String str = "Hello,,,World,,,每20秒,,,指定参数FixedDelay,,,";
        List<Map<String,String>> list = helloService.getTemp();
        log.info(str+ JSON.toJSONString(list));
        log.info("定时任务结束 ByFixedDelay:" + DateUtils.getDatetimeString());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    @SpringBootApplication
    @EnableScheduling
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    二、参数说明

    fixedDelay

    上一次任务执行完毕时间点之后多长时间再执行,任务的执行要等上一个任务执行结束。
    它的间隔时间是根据上次的任务结束的时候开始计时的。
    比如一个方法上设置了 fixedDelay=10*1000,那么当该方法某一次执行结束后,开始计算时间,当时间达到10秒,就开始再次执行该方法。

    @Scheduled(fixedDelay=10000)   //每隔10秒执行
    
    @Scheduled(fixedDelay=60*60*1000)   //每隔1小时执行
    
    • 1
    • 2
    • 3

    fixedRate

    上一次任务开始执行点之后指定时间后再执行(如果执行时间超过了间隔时间,那上一次任务执行完之后,立即执行下一个任务)
    fixedRate 理解起来比较麻烦,它的间隔时间是根据上次任务开始的时候计时的。比如当方法上设置了 fiexdRate=5000,该执行该方法所花的时间是2秒,那么3秒后就会再次执行该方法。
    但是这里有个坑,当任务执行时长超过设置的间隔时长,那会是什么结果呢。打个比方,比如一个任务本来只需要花2秒就能执行完成,我所设置的fixedRate=5000,但是因为网络问题导致这个任务花了7秒才执行完成。当任务开始时Spring就会给这个任务计时,5秒钟时候Spring就会再次调用这个任务,可是发现原来的任务还在执行,这个时候第二个任务就阻塞了(这里只考虑单线程的情况下,多线程后面再讲),甚至如果第一个任务花费的时间过长,还可能会使第三第四个任务被阻塞。被阻塞的任务就像排队的人一样,一旦前一个任务没了,它就立马执行。

    @Scheduled(fixedRate=60000)   //任务开始执行后隔60秒执行
    
    @Scheduled(fixedRate=60*60*1000)   //任务开始执行后隔1小时执行
    
    • 1
    • 2
    • 3

    initialDelay

    第一次任务将会延迟指定时间后启动

    @Scheduled(fixedDelay=60*60*1000,initialDelay=60*1000)   //第一次任务延迟1分钟启动,之后每隔1小时执行
    
    • 1

    cron

    该参数接受一个cron表达式,cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义。

    @Scheduled(cron="秒 分 时 日 月 周 年")   // 年不是必需的,可省略
    
    • 1

    三、cron 表达式

    @Scheduled(cron="秒 分 时 日 月 周 年")   // 年不是必需的,可省略
    
    • 1

    参数说明

    其中,每个时间字段都有对应的取值范围和特殊符号。下面是每个时间字段的详细说明:

    1、秒 (Seconds):取值范围为 0~59。例如,'0/5'表示每隔5秒触发一次。'*'表示每秒种都触发。允许使用特殊字符 , - * /
    
    2、分钟 (Minutes):取值范围为 0~59。例如,'0/5'表示每隔5分钟触发一次。'*'表示每分种都触发。允许使用特殊字符 , - * /
    
    3、小时 (Hours):取值范围为 0~23。例如,'0/2'表示每隔2小时触发一次。'*'表示每小时都触发。允许使用特殊字符 , - * /
    
    4、日期 (Day of Month):取值范围为 1~31。例如,'1,15'表示每月的1日和15日触发,'*'表示每天都触发。允许使用特殊字符 , - * ? / L W C
    
    5、月份(Month):取值范围为 1~12,也可以使用英文缩写JANFEBMAR等。例如,'1,6'表示一月和六月触发,'*'表示每个月都触发。允许使用特殊字符 , - * /
    
    6、星期 (Day of Week) :取值范围为 1~71 表示星期日,2 表示星期一,以此类推,也可以使用英文缩写 SUNMONTUE 等。例如,'2-6'表示星期一到星期五触发,'*' 表示每个星期都触发。允许使用特殊字符 , - * ? / L C #
    
    7、年份 (Year):可选字段,表示触发条件的年份。例如,'2023' 表示在2023年触发,'*' 表示每年都触发。允许使用特殊字符 , - * /
    
    // 在使用时,由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    除了取值范围,Cron 表达式还支持一些特殊符号,用于指定特定的触发条件,例如:

    星号(*):代表所有可能的取值,表示不限制该时间字段的取值范围。
    问号(?):仅在日期和星期字段中使用,表示不指定具体的取值,可以任意匹配。
    斜线(/):表示间隔触发,例如在分钟字段中,"*/5"表示每隔5分钟触发一次。"0/15"表示从第0分钟开始,每15分钟。"3/20"表示从第3分钟开始,每20分钟(它和"3,23,43")的含义一样
    逗号(,):用于指定多个取值,例如在小时字段中,"1,3,5" 表示在第 135 小时触发。
    减号(-):用于指定一个范围,例如在月份字段中,"3-6" 表示三月到六月触发。
    
    "L" 字符仅被用于天(月)和天(星期)两个子表达式,它是单词"last"的缩写
    如果在"L"前有具体的内容,它就具有其他的含义了。例如:"6L"表示这个月的倒数第6天
    注意:在使用"L"参数时,不要指定列表或范围,因为这会导致问题
    "W" 字符代表着工作日(Mon-Fri),并且仅能用于日历中。它用来指定离指定日的最近的一个星期日。大部分的商业处理都是基于工作周的,所以 W 字符可能是非常重要的。
    例如,日域中的 15W 意味着 "离该月15号的最近一个工作日"。 假如15号是星期六,那么 trigger 会在14(星期五)触发,因为星期伍比星期一离15号更近。
    "C" 字符代表"Calendar"的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实用性的案例

    "0 0 10,14,16 * * ?"  每天上午10,14,16"0 0/30 9-17 * * ?"   朝九晚五工作时间内每半小时
    "0 0 12 ? * WED" 表示每个星期三中午12"0 0 12 * * ?"   每天中午12点触发 
    每天上午10:15触发: "0 15 10 ? * *"   "0 15 10 * * ?"   "0 15 10 * * ? *"
    "0 15 10 * * ? 2005" 2005年的每天上午10:15触发 
    "0 * 14 * * ?"       在每天下午2点到下午2:59期间的每1分钟触发 
    "0 0/5 14 * * ?"     在每天下午2点到下午2:55期间的每5分钟触发 
    "0 0/5 14,18 * * ?"  在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 
    "0 0-5 14 * * ?"     在每天下午2点到下午2:05期间的每1分钟触发 
    "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:102:44触发 
    "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发 
    "0 15 10 15 * ?" 每月15日上午10:15触发 
    "0 15 10 L * ?"  每月最后一日的上午10:15触发 
    "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发 
    "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 
    "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 
    
    
    @Scheduled(cron = "*/5 * * * * ?")  \\每隔5秒钟执行一次
    
    @Scheduled(cron = "0 */1 * * * ?")  \\每隔一分钟执行一次
    
    @Scheduled(cron = "0 26,29,33 * * * ?")  \\在各个小时的26分、29分、33分执行一次
    
    @Scheduled(cron = "0 0 */2 * * ?")  \\每隔两小时执行一次
    
    @Scheduled(cron = "0 0 1 * * ?")  \\每天凌晨1点执行一次
    
    @Scheduled(cron = "0 0 6,15,20 * * ?")  \\每天的6点、15点、20点触发定时任务
    
    @Scheduled(cron = "0 0 2 1 * ?")  \\每月1号凌晨2点执行一次
    
    @Scheduled(cron = "0 0 23 L * ?")  \\每月最后一天23点执行一次
    
    @Scheduled(cron = "0 0 3 ? * L")  \\每周星期六凌晨3点执行一次
    
    @Scheduled(cron = "0 0 12 ? * SUN")  \\每周星期天中午12点执行一次
    
    @Scheduled(cron = "0 0 0 L * ?")  \\每个月的最后一天执行一次
    
    @Scheduled(cron = "0 0/5 9-17 * * MON-FRI")  \\工作日的早上 9 点到下午 5 点,每隔 5 分钟触发定时任务
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    Scheduled(cron=“0 */1 * * * ?”)
    每一分钟执行一次。比如第一次执行时间为2023-10-20 23:08:12,下一次2023-10-20 23:09:12,再下一次2023-10-20 23:10:12

    @Scheduled(cron = “10 * * * * ?”)
    每分钟的第十秒执行一次。比如第一次执行时间为2023-10-20 23:09:10,下一次2023-10-20 23:10:10,再下一次2023-10-20 23:11:10。 之所以用(23:09:10)举例,是因为上一个任务是在(23:08:12)才启动,所以任务只能从23:09:10开始

    @Scheduled(cron = “*/10 * * * * ?”)
    每十秒钟执行一次。比如第一次执行时间为2023-10-20 23:08:12,下一次2023-10-20 23:08:22,再下一次2023-10-20 23:08:32

    四、@Scheduled注意事项

    • spring的注解@Scheduled 需要写在实现方法上
    • 定时器的任务方法不能有返回值(如果有返回值,spring初始化的时候会告诉你有个错误、需要设定一个proxytargetclass的某个值为true),不能指向任何的参数
    • 如果该方法需要与应用程序上下文的其他对象进行交互,通常是通过依赖注入来实现
    • 实现类上要有组件的注解@Component

    五、配置文件

    1、fixedDelay

    @Scheduled(initialDelay = 5, fixedDelayString = "${erwin.fixed-delay:2}", timeUnit = TimeUnit.SECONDS)
    public void scheduledTaskByFixedDelay() {
    	log.info("定时任务开始 ByFixedDelay:" + DateUtils.getDatetimeString());
        log.info("Hello,,,World,,,指定参数fixedDelay,,,");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置文件 .yml

    erwin:
      fixed-delay: 5
    
    • 1
    • 2

    如果在配置文件中没有配置,则每隔2秒执行一次,如果配置了,就每隔5秒执行一次。initialDelay 表示,项目启动后,5秒开始执行第一次任务。
    注意:${erwin.fixed-delay:2},冒号前后不能有空格。

    2、fixedRate

    @Scheduled(initialDelay = 5, fixedRateString = "${erwin.fixed-rate:2}", timeUnit = TimeUnit.SECONDS)
    public void scheduledTaskByFixedRate() {
    	log.info("定时任务开始 ByFixedRate:" + DateUtils.getDatetimeString());
        log.info("Hello,,,World,,,指定参数fixedRate,,,");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置文件 .yml

    erwin:
      fixed-rate: 5
    
    • 1
    • 2

    3、cron

    如果配置文件没有配,就会使用默认的值。

    @Scheduled(cron = "${erwin.cron:0/10 * * * * ?}")
    public void scheduledTaskByCron() {
    	log.info("定时任务开始 ByCron:" + DateUtils.getDatetimeString());
        log.info("Hello,,,World,,,指定参数cron,,,");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置文件 .yml

    erwin:
      cron: 0/30 * * * * ?
    
    • 1
    • 2
  • 相关阅读:
    ElasticSearch常见避坑指南
    Apache HTTPD (CVE-2017-15715)换行解析漏洞复现
    安防监控系统/视频云存储/视频AI智能分析:人形检测算法应用汇总
    【无标题】
    Android中级——MVVM
    Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单
    DBA-现在应该刚刚入门吧
    亚马逊产品召回后如何重新发布商品?儿童睡衣,婴儿沐浴座椅,不锈钢儿童水杯被召回
    并发锁机制
    hexdump 命令 -e 选项
  • 原文地址:https://blog.csdn.net/qq_55342245/article/details/133966570