Cron表达式简单介绍 + Springboot定时任务的应用

news2024/12/29 23:16:14

前言
表达式是一个字符串,主要分成6或7个域,但至少需要6个域组成,且每个域之间以空格符隔开。

  • 以7个域组成的,从右往左是【年 星期 月份 日期 小时 分钟 秒钟】

秒 分 时 日 月 星期 年

  • 以6个域组成的,从右往左是【星期 月份 日期 小时 分钟 秒钟】

秒 分 时 日 月 星期

一、表达式域值说明

域值范围域值占位符备注
0~59,-*/
0~59,-*/
小时0~23,-*/
日期1~31或1~30,- * ? / L W C
月份1~12或JAN-DEC, - * /
星期1~7或SUN-SAT(SUN=1), - * ? / L C #1 表示星期天,2 表示星期一,依次类推
年份留空或1970-2099, - * /自动生成,工具不显示该值

二、表达式域占位符的说明

符号含义示例
*表示匹配域的任意值在分这个域使用 *,即表示每分钟都会触发事件。
?表示匹配域的任意值,但只能用在日期和星期两个域,因为这两个域会相互影响。要在每月的 20 号触发调度,不管每个月的 20 号是星期几,则只能使用如下写法:13 13 15 20 * ?。其中,因为日期域已经指定了 20 号,最后一位星期域只能用 ?,不能使用 *。如果最后一位使用 *,则表示不管星期几都会触发,与日期域的 20 号相斥,此时表达式不正确。
-表示起止范围在分这个域使用 5-20,表示从 5 分到 20 分钟每分钟触发一次。
/表示起始时间开始触发,然后每隔固定时间触发一次表示起始时间开始触发,然后每隔固定时间触发一次
,表示列出枚举值在分这个域使用 5,20,则意味着在 5 和 20 分每分钟触发一次。
L表示最后,只能出现在日和星期两个域在星期这个域使用 5L,意味着在最后的一个星期四触发。
W表示有效工作日(周一到周五),只能出现在日这个域,系统将在离指定日期最近的有效工作日触发事件。在日这个域使用 5W,如果 5 号是星期六,则将在最近的工作日星期五,即 4 号触发。如果 5 号是星期天,则在 6 号(周一)触发;如果 5 号为工作日,则就在 5 号触发。另外,W 的最近寻找不会跨过月份。
LW这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
#表示每个月第几个星期几,只能出现在星期这个域在星期这个域使用 4#2,表示某月的第二个星期三,4 表示星期三,2 表示第二个。

三、示例

表达式执行计划
*/5 * * * * ?每隔 5 秒执行一次
0 */1 * * * ?每隔 1 分钟执行一次
0 0 2 1 * ? *每月 1 日的凌晨 2 点执行一次
0 15 10 ? * MON-FRI周一到周五每天上午 10:15 执行作业
0 15 10 ? 6L 2002-20062002 年至 2006 年的每个月的最后一个星期五上午 10:15 执行作业
0 0 23 * * ?每天 23 点执行一次
0 0 1 * * ?每天凌晨 1 点执行一次
0 0 1 1 * ?每月 1 日凌晨 1 点执行一次
0 0 23 L * ?每月最后一天 23 点执行一次
0 0 1 ? * L每周星期天凌晨 1 点执行一次
0 26,29,33 * * * ?在 26 分、29 分、33 分执行一次
0 0 0,13,18,21 * * ?每天的 0 点、13 点、18 点、21 点都执行一次
0 0 10,14,16 * * ?每天上午 10 点,下午 2 点,4 点执行一次
0 0/30 9-17 * * ?朝九晚五工作时间内每半小时执行一次
0 0 12 ? * WED每个星期三中午 12 点执行一次
0 0 12 * * ?每天中午 12 点触发
0 15 10 ? * *每天上午 10:15 触发
0 15 10 * * ?每天上午 10:15 触发
0 15 10 * * ? *每天上午 10:15 触发
0 15 10 * * ? 20052005 年的每天上午 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:10 和 2: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-20052002 年至 2005 年的每月的最后一个星期五上午 10:15 触发
0 15 10 ? * 6#3每月的第三个星期五上午 10:15 触发

四、简单介绍一下springboot的几种定时任务的使用

方法一:单线程的定时器

如果有多个直接计划的情况下,可能会在运行时受到其他任务的影响

@Slf4j
@Component
@EnableScheduling
public class ScheduledConfiguration{
    /**
     * cron=0 0/1 * * * ?
     * 1,改方法从当前日期的0分0秒开始,每间隔1分钟执行一次,每次执行的时间都是整分整秒
     * 2,如果当前日期的0分0秒已过,将会从当前日期的最近一分钟的0秒开始运行
     * 举例:
     * 当前时间:2023-04-13 13:21:23
     * 根据运算规则,已经过了整点【13:00:00】,
     * 则会从最近一分钟的0秒开始,由于时间已经是21分23秒,则已经不能从21分开始,
     * 那么最近的一分钟是22分,所以程序会从22分0秒开始运行,然后每间隔一分钟再运行一次
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    private void print() {
        log.info("当前时间:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    }
}

可以从下图看到确实是按照执行计划在打印时间
在这里插入图片描述
上述代码中主要用到了两个注解,一个是方法注解@Scheduled,一个是类注解@EnableScheduling
@Scheduled标记的方法,将会按照cron表达式的执行计划运行方法,但要想计划生效还需要在类名上添加@EnableScheduling注解来告诉容器,该类存在定时处理的任务,否则将不会按照计划执行方法

方法二:多线程定时任务

为了解决多任务出现冲突的情况,可以引入另一个注解@Async,同样也需要告诉容器该类存在多线程的执行计划@EnableAsync

在看多计划任务使用多线程的方式来解决单线程执行多计划出现相互影响的问题的时候,我们先来看一下怎么在单线程的情况下混乱多个定时任务。

首先我们在类里边再加一个或多个执行计划的方法,然后在某个或多个方法中让它的运行时间加长,以此来实现打乱其他任务的执行时间,从而让执行计划在设置的时间点不能正常运行,通过此方式
我们可以看到在原定的时间点方法并没有运行,当它运行的时候,已经不是原定时间了,已经不在预定时间点,如果在这时候出现一个很长时间都无法完成的任务,你会发现原本需要处理的任务没有按时处理,这种情况下可能是致命的。废话不多说,我们来搞一下,让事件复现吧。

下面我创建两个定时任务,两个都按照间隔5秒的计划运行代码,但我让其中一个任务执行的时间更长,让另一个定时任务在规定的时间难以运行,从而改变原有的运行时间轨迹。

@Slf4j
@Component
@EnableScheduling
public class ScheduledConfiguration {
    @Scheduled(cron = "0/5 * * * * ?")
    private void print1() {
        log.info("1).执行计划a -> 当前时间:{},执行线程:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), Thread.currentThread().getName());
        try {
            Thread.sleep(13000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Scheduled(cron = "0/5 * * * * ?")
    private void print2() {
        log.info("2).执行计划b -> 当前时间:{},执行线程:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), Thread.currentThread().getName());
    }
}

来看一下执行结果吧,相信不会让你失望的,你会发现第二个执行计划的执行时间已经被打乱了,并没有按照间隔5秒运行,并且能看到执行线程都是同一个,很显然单线程的情况下是不能做到两两兼容的,而且如果某一个任务执行时间无限加长,或者卡死,那其他的任务可能都没法运行了
在这里插入图片描述
在讲解开始的时候我们已经了解到可以通过加两个注解的方式来解决这个问题,那究竟是不是像我们假设的这样,那让我们拭目以待吧。

首先来搞一下代码,先在两个定时任务的方法上添加注解@Async,然后在类上添加注解@EnableAsync

@Slf4j
@Component
@EnableScheduling
@EnableAsync
public class ScheduledConfiguration {
    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    void print1() {
        log.info("1).执行计划a -> 当前时间:{},执行线程:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), Thread.currentThread().getName());
        try {
            Thread.sleep(13000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    void print2() {
        log.info("2).执行计划b -> 当前时间:{},执行线程:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), Thread.currentThread().getName());
    }
}

那接下来就到了我们来看结果的时候了,你会很神奇的发现居然计划b都是按每隔5秒运行,并且计划a在运行的时候不管运行多久,就会按照最近时间0秒开始,间隔5秒运行,所以秒钟永远指挥出现05,那这不就对上了吗,多线程的情况下执行计划都互不相干的按照各自的规则运行着,即使其他的计划卡死,或者时间执行再长,也不会影响其他的执行计划了
在这里插入图片描述

方法三:动态执行计划

顾名思义就是不用把计划写死在注解里,这种场景比较多,有时候往往要修改执行计划的时候,如果按照写死的情况,真的很不方便,为啥不方便,我就不用说了吧。

要想实现多态执行计划呢,那肯定是少不了下一丢丢功夫了,至少比之前的两种要麻烦一些,毕竟不是写在注解上,那当然需要用到spring的接口SchedulingConfigurer,然后实现方法configureTasks,在方法里边写自己的动态代码也就是获取的执行计划,可以是一个配置文件,也可以是读取数据库,怎么方便怎么来吧,下面介绍修改配置文件的方式来调整执行计划。

  • 配置文件添加执行计划表达式,如果不添加则使用默认计划
# 每隔5秒执行一次
spring.scheduled.cron=0/5 * * * * ?
  • 配置文件搞了那就来搞一搞代码吧,废话不多说开干
@Slf4j
@Component
@EnableScheduling
public class ScheduledDynamicsConfiguration implements SchedulingConfigurer {
    /**
     * 这里是一个默认的执行计划,默认从0秒开始间隔5秒执行一次
     */
    private static final String defaultScheduledCron = "0/5 * * * * ?";

    /**
     * 读取配置文件
     *
     * @return
     */
    private Properties properties() {
        Properties prop = new Properties();
        try {
            // 加载配置文件
            prop.load(ScheduledDynamicsConfiguration.class.getResourceAsStream("/application.properties"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return prop;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1.添加任务内容(Runnable)
                () -> log.info("动态执行计划 -> 当前时间:{},执行线程:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), Thread.currentThread().getName()),
                //2.设置执行周期(Trigger)
                triggerContext -> {
                    // 2.1 读取配置文件
                    Properties prop = properties();
                    //2.3 返回执行周期(Date)
                    return new CronTrigger(prop.getProperty("spring.scheduled.cron", defaultScheduledCron)).nextExecutionTime(triggerContext);
                }
        );
    }
}

代码也写完了那就开始运行吧,来看看运行效果,并且我们来修改执行

  • 初始application.properties的执行计划是间隔5秒执行一次
  • spring.scheduled.cron=0/5 * * * * ?
    在这里插入图片描述
  • 运行一段时间后将执行计划修改位3秒执行一次
  • spring.scheduled.cron=0/3 * * * * ?
    在这里插入图片描述
  • 我在将执行计划修改为13秒执行一次
  • spring.scheduled.cron=0/13 * * * * ?
    在这里插入图片描述
  • 注意如果在开发阶段做测试的话你修改源码的配置文件时不会生效的,除非你做了热部署,否则你只能修改编译之后target下的配置文件才能生效,如果是生产环境当然就没有这个问题,毕竟生产环境的代码就是已经编译打包之后的项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【精华】表格识别技术-MI

表格识别是指将图片中的表格结构和文字信息识别成计算机可以理解的数据格式,在办公、商务、教育等场景中有着广泛的实用价值,也一直是文档分析研究中的热点问题。围绕这个问题,我们研发了一套表格识别算法,该算法高效准确地提取图…

RabbitMq 的消息可靠性问题(二)---MQ的消息丢失和consumer消费问题

前言 RabbitMq 消息可靠性问题(一) — publisher发送时丢失 前面我们从publisher的方向出发解决了发送时丢失的问题,那么我们在发送消息到exchange, 再由exchange转存到queue的过程中。如果MQ宕机了,那么我们的消息是如何确保可靠性的呢?当消…

SQL的函数

文章目录一、SQL MIN() Function二、SQL SUM() 函数三、SQL GROUP BY 语句四、SQL HAVING 子句五、SQL EXISTS 运算符六、SQL UCASE() 函数总结一、SQL MIN() Function MIN() 函数返回指定列的最小值。 SQL MIN() 语法 SELECT MIN(column_name) FROM table_name;演示数据库 …

Numba witch makes Python code fast

一. 前言:numba,让python速度提升百倍 python由于它动态解释性语言的特性,跑起代码来相比java、c要慢很多,尤其在做科学计算的时候,十亿百亿级别的运算,让python的这种劣势更加凸显。 办法永远比困难多&a…

ASP.NET Core MVC 从入门到精通之接化发(二)

随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生&#xff0c…

4.13实验 加测试题目

今天是个好日子,要搞栈的实验 没啥就是链栈和顺序栈 和出栈入栈,强大都是从最基本开始的 来和我一起写写吧 //顺序栈 typedef struct node{int *base;int *top;int sizer; }shed;//链栈 typedef struct Node{ int data; struct Node* next; }*stact,link; //顺序栈的初始化…

《绝对坦率》速读笔记

文章目录书籍信息概览(第一部分 一种新的管理哲学)建立坦率的关系给予并鼓励指导了解团队中每个人的动机协同创造成果(第二部分 工具和技巧)关系指导团队结果书籍信息 书名:《绝对坦率:一种新的管理哲学》…

北邮22信通:(12)二叉树的遍历书上代码完整版

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章: 下一篇文章: 目录 一.储存最简单数据类型的二叉树 代码部分: 代码效果: 运行结果&#xff1a…

解决JD-GUI-1.6.6 中文乱码

一、背景 在window环境下使用中遇到了乱码问题。 问题有两个: 一、从反编译代码的界面 CTRLC 复制是如果选中内容包含中文,贴到其他编辑器时,中文丢失。 二、打开xml文件、properties文件等包含中文时。中文在反编译界面中显示乱码。用其他工…

java反射教程

反射(Reflection)是 Java中的一种机制,它是一种特殊的面向对象编程技术。在 Java中,反射可以分为静态反射和动态反射两种。静态反射是指在 Java程序运行时才进行的一种反射,它可以保证程序运行时不会出现内存泄漏等错误…

数据分析的作用和意义?

数据分析的作用和意义?在当下数字化转型发展的大环境中,数据也成为企业商业成功与否的重要基础,如何利用好数据分析问题预测未来也成为更多企业面临的首要问题。而随时大数据的不断渗透,数据量和数据类型也越来越多,数…

asp.net车辆管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net车辆管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语言开发 asp.net车辆管理系统VS开发sqlserver数…

【CSIG图像图形技术挑战赛-开放世界目标检测竞赛】火热报名中!

竞赛名称:开放世界目标检测竞赛/Few Shot)主办方: 中国图象图形学学会(CSIG)合作方: 360集团竞赛目的与意义:目标检测是计算机视觉中的核心任务之一,主要目的是让计算机可以自动识别图片中目标的类别&#…

Windows File Recovery使用教程

Windows File Recovery简介 Windows File Recovery是微软在2020年发布的命令提示符文件恢复工具,它不仅具有高成功率和高安全性,还适用于不同的文件系统和文件丢失场景。如果你需要从本地硬盘、USB设备、SD卡等设备中恢复意外丢失或删除的JPEG、PDF、…

分析Spring事务管理原理及应用

目录 一、Spring事务管理介绍 (一)基本理论 (二)实际工作中的举例 (三)简单应用举例 二、Spring事务配置介绍 (一)Spring事务属性介绍 传播属性(传播行为&#xff…

车身控制模块BCM(Body Control Module)

1.BCM概述 车身控制模块BCM是高集成度的芯片。BCM的英文全称是Body Control Module。其控制对象是采用高灵敏度带唤醒及睡眠检测的高频收发器,实现车门车窗遥控上锁与开锁、电动后视镜、中控门锁、玻璃升降装置、车灯(远光灯、近光灯、位置灯、制动灯、转向灯、雾灯…

【RocketMQ】主从模式下的消费进度管理

在【RocketMQ】消息的拉取一文中可知,消费者在启动的时候,会创建消息拉取API对象PullAPIWrapper,调用pullKernelImpl方法向Broker发送拉取消息的请求,那么在主从模式下消费者是如何选择向哪个Broker发送拉取请求的? 进…

【Linux】项目自动化构建工具-make/Makefile

文章目录1.make/Makefile的重要性2.规则及使用使用规则3.Makefile编译多文件1.make/Makefile的重要性 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中&#xf…

2023美赛春季赛Z题模型代码

已经完成模型代码,仅供大家参考,需要更多请看文末 一、问题分析 首先需要收集与奥运会举办城市/国家相关的历史数据。这需要涉及诸如经济、土地利用、人类满意度(包括运动员和观众)、旅行、基础设施建设、环境影响等多个方面。数…

(二)【软件设计师】计算机系统—CPU运算器控制器

文章目录一、CPU1.计算机硬件基本组成(了解)2.中央处理单元(了解)3.CPU组成4.例题二、运算器1.运算器有两个主要功能2.简要介绍运算器中各组成部件的功能三、控制器1.例题2.组成部分四、总结一、CPU 1.计算机硬件基本组成&#x…