一文详解SpringBoot 定时任务(cron表达式)

IDE:IntelliJ IDEA 2022.2.3 x64
操作系统:win10 x64 位 家庭版
JDK: 1.8


文章目录

  • 一、如何开启一个SpringBoot定时任务?
  • 二、cron表达式详解
    • 2.1 语法格式
    • 2.2 符号解析
      • 2,2.1 通用符号: , - * /
      • 2.2.2 专有符号:?L w # c
    • 2.3 测试运行
  • 三、fixedRate & fixedDelay
    • 3.1 fixedRate
    • 3.2 fixedDelay
  • 四、如何异步多线程的执行SprigBoot定时任务?
  • 资料参考


提示:以下是本篇文章正文内容,下面案例可供参考

一、如何开启一个SpringBoot定时任务?

在我们日常开发中,开启并使用一个SpringBoot定时任务的大致步骤通常按如下所示

步骤

①在启动类上添加@EnableScheduling开启定时任务

示例代码如下

//开启定时任务
@EnableScheduling
@SpringBootApplication
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}}

②编写定时任务,在其上添加@Scheduled设置任务执行时间

示例代码如下

 //每3秒执行一次@Scheduled(fixedRate = 3000)public void notifyA(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

③将定时任务所在的类上添加@Component

示例代码如下

@Component
public class springTimerTask {//每3秒执行一次@Scheduled(fixedRate = 3000)public void notifyA(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}
}

运行如下

在这里插入图片描述


二、cron表达式详解

在日常开发中,可以借助下面的网站快速生成cron表达式,提高开发效率

👉cron表达式在线生成器

2.1 语法格式

形式*******
字段SecondsMinutesHoursDayofMonthMonthDayofWeekYear
含义星期年(可选)
范围0-590-590-231-311-12(JAN-DEC)1-7 (SUN-SAT)
符号, - * /, - * /, - * /, - * /, - * / ? L C #, - * /, - * / ? L C #

备注

DayofWeek字段有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一,余下依次类推
Year字段有效范围为1970-2099年

2.2 符号解析

2,2.1 通用符号: , - * /

  • ,表示列出枚举值。例如:在Minutes域使用5,20,表示在时间的分钟数为5、20时触发事件
  • -表示范围。例如在Minutes域使用5-20,表示在时间的分钟数为5到20时每分钟都触发事件
  • *表示匹配该域的任意值。假如在Minutes:域使用,表示时间分钟数不做限制,每分钟都触发事件
  • /表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,表示时间的分钟数为5时触发一次,后隔20分钟即25、45再分别触发一次事件

举例说明

  • 0/2 * * * * ? : 表示每2秒 执行任务
  • 0 0/2 * * * ?表示每2分钟 执行任务
  • 0 0 2 1 * ?表示在每月的1日的凌晨2点调整任务

2.2.2 专有符号:?L w # c

  • ?只能用在DayofMonth和DayofWeek两个域,由于DayofMonthi和DayofWeek互斥,须对其一设置?
  • L表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用L,意味着在最后的一个星期四触发
  • W表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件
  • WL这两个字符可以连用,表示在某个月最后一个工作日
  • #用于确定每个月第几个星期几,只能出现在DayofWeek域。例如在4#2,表示某月的第二个星期三
  • C只能用在DayofMonth和DayofWeeki两个域,需要关联日历,如果没关联可以忽略

举例说明

  • 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-2005: 2002年至2005年的每月的最后一个星期五上午10:15触发

注意

springBoot只支持cron表达式中的专有符号?,也仅仅支持6位的cron表达式,7位的不支持!!!

2.3 测试运行

示例代码如下

 //每2秒执行一次@Scheduled(cron = "0/2 * * * * ?")public void notifyA(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

运行如下

在这里插入图片描述


三、fixedRate & fixedDelay

如下可知,@Schedule里还可以使用以下两种类型的表达式,分别是“fixedDelay = xxx” 与 “fixedRate = xxx”
在这里插入图片描述

3.1 fixedRate

fixedRate属性是@Schedule注解中的一个属性,它表示以固定的频率执行某个方法或任务。此属性用于指定任务执行的时间间隔,单位为毫秒。

例如,如果设置为2000(即2秒),则任务将每隔2秒执行一次。

示例代码如下

//每2秒执行一次@Scheduled(fixedRate = 2000)public void notifyB(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

运行如下

在这里插入图片描述

注意

fixedRate是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。

测试代码如下

	//模拟任务阻塞4s,每2秒执行一次@Scheduled(fixedRate = 2000)public void notifyB() throws InterruptedException {Thread.sleep(4000);String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

运行如下

在这里插入图片描述

3.2 fixedDelay

fixedDelay属性是@Schedule注解中的一个属性,它表示以固定的时间间隔执行某个方法或任务,并在每次执行完成后等待指定的延迟时间再执行下一次。

fixedDelay属性用于指定任务执行之间的延迟时间,单位为毫秒。

例如,如果设置为2000(即2秒),则任务将每隔2秒执行一次,并且在每次执行完成后等待2秒再执行下一次。

示例代码如下

   //每2秒执行一次,并延迟2s@Scheduled(fixedDelay = 2000)public void notifyB(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

运行如下

在这里插入图片描述

注意

fixedDelay的执行时间是以上一次方法执行完开始算起,比如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次

举个具体的例子,如果在一个方法上设置了fixedDelay=5*1000(即5秒),那么当该方法某一次执行结束后,开始计算时间,当时间达到5秒,就开始再次执行该方法。这意味着无论任务实际执行需要多长时间,每个任务之间的延迟时间始终保持不变。

测试代码如下

	//模拟上次任务阻塞4s,然后间隔2秒执行下一次@Scheduled(fixedDelay = 2000)public void notifyB() throws InterruptedException {Thread.sleep(4000);String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}

运行如下

在这里插入图片描述


四、如何异步多线程的执行SprigBoot定时任务?

最简单的做法如下所示

步骤

①在启动类上添加注解@EnableAsync开启异步执行

示例代码如下

@EnableScheduling
@SpringBootApplication
@EnableAsync
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}}

②在定时任务上添加@Asynci设置异步执行

示例代码如下

@Component
public class springTimerTask {//每2秒执行一次@Async@Scheduled(cron = "0/2 * * * * ?")public void notifyA(){String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}//每3秒执行一次@Async@Scheduled(cron = "0/3 * * * * ?")public void notifyB() throws InterruptedException {String now = new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date());String name = Thread.currentThread().getName();System.out.println(name+"通知已发送"+",发送时间为"+now);}
}

运行如下

在这里插入图片描述

why?

Spring默认单线程的定时任务,如果不开启异步,多个任务都是同一个线程在处理,如果这个线程内的任务比较耗时,会导致后续任务延期; 开启异步后,每个任务都会从线程池里分配一个线程去完成,避免耗时长的任务,导致其他任务延期,故而上述代码在中存在多个线程在执行同一个任务的情况;

不信?请看如下不开启异步,多个定时任务同时运行的情形

在这里插入图片描述


资料参考

https://www.bilibili.com/video/BV1JR4y1N7Ni/?p=7&spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=5a34715e416a427a73a3ca52397848b5

https://blog.csdn.net/u011066470/article/details/107529863?ops_request_misc=&request_id=&biz_id=102&utm_term=SpringBoot%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1:%20cron%E8%A1%A8%E8%BE%BE%E5%BC%8F&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-107529863.142v96pc_search_result_base9&spm=1018.2226.3001.4187

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cucumber-JVM的示例和运行解析

Cucumber-JVM 是一个支持 Behavior-Driven Development (BDD) 的 Java 框架。在 BDD 中,可以编写可读的描述来表达软件功能的行为,而这些描述也可以作为自动化测试。 Cucumber-JVM 的最小化环境 Cucumber-JVM是BDD的框架, 提供了GWT语法的相…

Deepin更换仿Mac主题

上一篇博客说了要写一篇deepin系统的美化教程 先看效果图: 准备工作: 1.你自己 嘻嘻嘻 2.能上网的deepin15.11电脑 首先去下载主题 本次需要系统美化3部分:1.图标 2.光标 3.壁纸 开始之前,请先把你的窗口特效打开,…

论文阅读《Rethinking Efficient Lane Detection via Curve Modeling》

目录 Abstract 1. Introduction 2. Related Work 3. BezierLaneNet 3.1. Overview 3.2. Feature Flip Fusion 3.3. End-to-end Fit of a Bezier Curve 4. Experiments 4.1. Datasets 4.2. Evalutaion Metics 4.3. Implementation Details 4.4. Comparisons 4.5. A…

读论文之StoryGAN

StoryGAN: A Sequential Conditional GAN for Story Visualization 本文参考StoryGAN-CSDN博客https://blog.csdn.net/Forlogen/article/details/93378325 ​​​​​​论文阅读:StoryGan - 简书 (jianshu.com)https://www.jianshu.com/p/f28d6f472396 项目源码&…

完全背包问题,原理剖析,公式推导,OJ详解

文章目录 前言一、完全背包的状态设计1、状态设计2、状态转移方程3、对比0/1背包问题4、时间复杂度分析 二、完全背包问题的优化1、时间复杂度优化2、空间复杂度优化 三、OJ练习裸题完全背包离散化最小值 前言 完全背包问题,相比0/1背包问题,实就每个物品…

深度学习 | DRNN、BRNN、LSTM、GRU

1、深度循环神经网络 1.1、基本思想 能捕捉数据中更复杂模式并更好地处理长期依赖关系。 深度分层模型比浅层模型更有效率。 Deep RNN比传统RNN表征能力更强。 那么该如何引入深层结构呢? 传统的RNN在每个时间步的迭代都可以分为三个部分: 1.2、三种深层…

如何将语音版大模型AI接入自己的项目里(语音ChatGPT)

如何将语音版大模型AI接入自己的项目里语音ChatGPT 一、语音版大模型AI二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例5、智能生成API代码 三、 如何获取appKey和uid1、申请appKey:2、获取appKey和uid 四、重要说明 一、语音版大模型AI 基于阿里通义千问、百…

IT安全:实时网络安全监控

了解庞大而复杂的网络环境并非易事,它需要持续观察、深入分析,并对任何违规行为做出快速反应。这就是为什么实时网络安全监控工具是任何组织 IT 安全战略的一个重要方面。 网络攻击和合规性法规是 IT 安全的两个主要驱动因素。同时,数据泄露…

关于“Python”的核心知识点整理大全45

目录 15.4.6 绘制直方图 die_visual.py 注意 15.4.7 同时掷两个骰子 dice_visual.py 15.4.8 同时掷两个面数不同的骰子 different_dice.py 15.5 小结 第 16 章 16.1 CSV 文件格式 16.1.1 分析 CSV 文件头 highs_lows.py 注意 16.1.2 打印文件头及其位置 highs_l…

Redis 核心知识总结

Redis 核心知识总结 认识 Redis 什么是 Redis? Redis 是一个由 C 语言开发并且基于内存的键值型数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 有以下几个特…

案例189:基于微信小程序的高校教务管理系统设计与实现

文末获取源码 开发语言:Java 框架:springboot JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder …

Python办公自动化Day3-python-docx

目录 文章声明⭐⭐⭐让我们开始今天的学习吧!新建打开保存新建与保存打开 操作段落添加段落/查询段落数删除段落内容但未删除段落插入段落插入分页符 段落样式对齐方式自带样式缩进与间距 Run介绍/读取Run添加/修改/删除RunRun样式 小案例 文章声明⭐⭐⭐ 该文章为…

通过Python将PDF转为文本,快速提取PDF中的文字

快速高效地从PDF文档中提取信息对于专业人士来说非常重要。处理大量PDF文件时,将PDF转换为可编辑的文本格式可以节省时间和精力。而强大的Python语言正是在这些方面发挥其作用。利用Python中丰富的API,我们可以轻松在Python程序中将PDF转换为文本&#x…

《深入理解C++11:C++11新特性解析与应用》笔记四

第四章 新手易学,老兵易用 4.1 右尖括号>的改进 在 C98 中,有一条需要程序员规避的规则:如果在实例化模板的时候出现了连续的两个右尖括号 >,那么它们之间需要一个空格来进行分隔,以避免发生编译时的错误。C98 会将>&g…

MidJourney笔记(9)-daily_theme-docs-describe

/daily_theme 切换 #daily-theme 频道更新的通知。 但我发现在对话框那里,是没有这个命令的: 但官网是有介绍,不知道是不是版本问题还是这个命令已经无效。 但后来,我发现这个命令是要在Midjourney服务对话框那里才有,在我们后面添加的Mid

Linux的账号及权限管理

一.管理用户账号 1.1 用户账户的分类 1.1.1 用户账号的分类 超级用户:(拥有至高无上的权利) root用户是Linux操作系统中默认的超级用户账号,对本主机拥有最高的权限,系统中超级用户是唯一的。普通用户: …

2023年12月电子学会Scratch图形化编程一级真题及答案

2023年12月电子学会Scratch图形化编程一级真题及答案 一、单选题(共25题,共50分) 1. 观察下列每个圆形中的四个数,找出规律,在括号里填上适当的数?( ) A. 9 B. 17 C. 21 D. 5 试题编号:202306…

信息网络协议基础-IPv6协议

文章目录 概述为什么引入IP服务模型IPv4的可扩展性问题解决方法***CIDR(Classless Inter-Domain Routing, 无类别域间寻路)前缀汇聚***前缀最长匹配***NAT(网络地址转换)存在的问题解决方案路由表配置***局限性IPv6协议头标IPv6地址表示前缀类型单播地址链路局部地址(Link-Loca…

第十二章:实验案例:使用rsync构建镜像网站

实验环境 某公司在深圳、北京两地各放置了---台网站服务器,分别应对南北大区内不断增长的客户访问需求.两台服务器的网站文档必须保持--致,如图12.3所示,同步链路已通过VPN专用线路实现。 需求描述 1,服务器A(北京〉…

k8s快速搭建

VMware16Pro虚拟机安装教程VMware16.1.2安装及各版本密钥CentOS7.4的安装包:提取码:lp6qVMware搭建Centos7虚拟机教程 搭建完一个镜像 关机 拍摄一个快照,克隆两个作为子节点 0. 环境准备 在开始之前,部署Kubernetes集群机器需要满足以下几个条件&#…