Spring boot定时任务@Scheduled

2023-11-01

1.前言:

@Scheduled 参数可以接受两种定时的设置,一种是我们常用的cron="*/6 * * * * ?",一种是 fixedRate = 6000,两种都表示每隔六秒打印一下内容:
@Scheduled(cron = “0 0 0 * * ?”) // 每日凌晨
@Scheduled(cron = “0 0/10 * * * ?”) // 每10分钟
@Scheduled(cron = “0 30 8-18 ? * MON-FRI”) //每周一到周五,8:30到18:30

@Scheduled(fixedDelay = 5000) :上一次执行完毕时间点之后5秒再执行
fixedDelay:在上一次执行完之后等xxx毫秒(xxx就是fixedDelay = 5000中的5000)再执行,循环下去,上一次执行多久都没关系 ,反正上一次执行完后xxx毫秒我才执行
@Scheduled(fixedDelay = 5000, initialDelay=8000)
initialDelay:第一次运行次要等xxx毫秒才能执行,比如:假设原来是14:00:00 开始执行这个,但是设置了initialDelay=8000,那么要在8000毫秒后才能执行这个方法,也就是14:00:08才真正执行
@Scheduled(fixedRate = 5000) :上一次开始执行时间点之后5秒再执行
fixedRate:这个有点蛋疼…,举个例子:比如:假设有5个执行时间点 间隔是5000毫秒:分别是:
T1:14:00:00
T2:14:00:05
T3:14:00:10
T4:14:00:15
T5:14:00:20
如果T1执行时间花了4秒,也就是到了14:00:04,那么你会看到14:00:05分就开始执行了T2,很正常,此时T1结束时间和T2开始时间只差1000毫秒,没毛病
如果T1执行时间花了8秒,怎么办?这时T1执行完的时间是14:00:08,已经覆盖了T2的时间,T2在14:00:05到14:00:08是等等状态。现在是14:00:08,看起来接着是T3执行,
但实际不是,而是立马执行T2,立马执行T2,立马执行T2(T2说:我不管,T1搞我超时了,我无论也是执行),这时你会发现T2的执行时间(也就是第2次执行时间 )是:14:00:08,真的是立马。。。
如此类推,只要时执行时间被覆盖了的,到它了就立马执行
@Scheduled(initialDelay=8000, fixedRate=5000) :第一次延迟8秒后执行,之后按fixedRate的规则每5秒执行一次
 

2.pom包配置:

pom包里面只需要引入springboot starter包即可

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

注意:如果在Windows上运行SpingBoot上面的pom.xml的配置即可,但是要打成jar包上传到Linux上运行的话还需要添加如下配置

    <build>
        <finalName>SpringBootTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

3.启动类启用定时:

在启动类上面加上@EnableScheduling即可开启定时

@SpringBootApplication
@EnableScheduling
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

4.创建定时任务实现类:

定时任务1:

@Component
public class test1Task {

    private int count=0;

    @Scheduled(cron="*/6 * * * * ?")
    private void process(){
        System.out.println("this is scheduler task runing  "+(count++));
    }

}

定时任务2:

@Component
public class test2Task {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(fixedRate = 6000)
    public void reportCurrentTime() {
        System.out.println("现在时间:" + dateFormat.format(new Date()));
    }

}

运行结果:

this is scheduler task runing  0
现在时间:14:23:17
this is scheduler task runing  1
现在时间:14:23:23
this is scheduler task runing  2
现在时间:14:23:29
this is scheduler task runing  3
现在时间:14:23:35

5.补充:cron表达式

字段 允许值 允许的特殊字符 备注
0-59 , - * / 标准实现不支持此字段。linux crontab 命令就不支持,最小的执行时间是一分钟,如果非想实现秒级别的可参考:linux crontab 实现每秒执行
0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C 需要考虑月的天数,如有28天或30天的,? L W只有部分软件实现了
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C # ? L W只有部分软件实现了。Linux和Spring的允许值为0-7,0和7为周日;Quartz的允许值为1-7,1为周日
年(可选) 留空, 1970-2099 , - * / 标准实现不支持此字段。linux crontab 命令就不支持

  其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?

"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 * * ? 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: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触发 
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

有些子表达式能包含一些范围或列表
例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”

“*”字符代表所有可能的值
因此,“*”在子表达式(月)里表示每个月的含义,“*”在子表达式(天(星期))表示星期的每一天

“/”字符用来指定数值的增量
例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟
在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样

“?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值
当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”

“L”字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写
但是它在两个子表达式里的含义是不同的。
在天(月)子表达式中,“L”表示一个月的最后一天
在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT
如果在“L”前有具体的内容,它就具有其他的含义了
例如:“6L”表示一个月的倒数第6天,“FRIL”表示一个月的最后一个星期五
注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题
例子:
    # 每月的最后1天
    0 0 L * * *

    说明:
    Linux
    *    *    *    *    *
    -    -    -    -    -
    |    |    |    |    |
    |    |    |    |    +----- day of week (0 - 7) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
    |    |    |    +---------- month (1 - 12) OR jan,feb,mar,apr ...
    |    |    +--------------- day of month (1 - 31)
    |    +-------------------- hour (0 - 23)
    +------------------------- minute (0 - 59)

补充:常用命令
# 编辑定时任务
crontab -e
# 显示定时任务
crontab -l
# 查看执行的日志
cat /var/log/cron

还可以用如下工具验证下次执行的时间https://tool.lu/crontab/ 非常的方便
 

6.遇到的坑:

注:有一个需要每个月的最后一天晚上的九点半执行调度任务,本以为这样写@Scheduled(cron="0 38 21 L * ?")就OK了,结果报错Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'process': For input string: "L"
原因:错误的根源是 Spring 的表达式只是 cron表达式的子集,它不包含year字段,并且不能使用所有特殊字符,比如L和W,大部分的文档有误导。
解决:

@Scheduled(cron = "0 38 21 28-31 * ?")
public void execute() {
	final Calendar c = Calendar.getInstance();
	if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) {
		//是最后一天
		System.out.println("是最后一天,开始执行调度任务");
	}
}
// 或者:
@Scheduled(cron = "0 38 21 28-31 * ?")
public void reptilian() {
    final Calendar calendar = Calendar.getInstance();
    //如果不是最后一天
    if (!(calendar.get(Calendar.DATE) == calendar.getActualMaximum(Calendar.DATE))) {
        return;
    }
    // 执行业务逻辑代码
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring boot定时任务@Scheduled 的相关文章

  • 高通9008刷机

    1 进入9008模式 第一种方法 adb reboot edl 第二种方法 手机按钮进入 第三种方法 小米安全通线 第四种方法 短路接点 2 需要安装安卓驱动 高通驱动 QFIL软件 3 需要下载ROM包 4 解压ROM包 5 打开QFIL
  • 毕业季

    进入六月 毕业的氛围越来越浓 虽然忙 但更多的是不舍 四年 转眼之间 大一在高密校区的岁月仍历历在目 6 10 从公司请假 早上八点半去图书馆布置创新比赛的展板 6 11 休整一天 PPT准备6 12号早上的答辩 6 12 早八点半 在中德
  • 欧科云链让科技赋能乡村教育,获公益时报等主流媒体报道...

    中国经济网 公益时报前线报道 近日 欧科云链CSR团队到访饶河县饶河农场中心小学 为该校的人工智能创客实验室注入了新的活力 这一举措旨在助力学校推进人工智能教育 为农村学生提供更广阔的发展机会 饶河农场中心小学一直以来致力于创新教育 自20
  • nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 的解决办法

    问题概述 在基于微服务架构风格的项目开发过程中 为了提高快速开发的目的 提高开发效率 集成了 MyBatisPlus 对于 MyBatisPlus 封装的 CRUD API 接口已经非常强大了 但是有时还是需要使用其动态 SQL 的拼接 在

随机推荐

  • 性能测试之性能优化篇

    目录 为什么进行性能测试 性能测试的目的 服务性能优化的思考 衡量系统性能常用的指标 系统性能计数器 性能测试分类 如何合理的规划我们的架构性能 最后拿数据说话 性能优化原则 性能优化的方法 性能优化的分层思想 所有的优化都会对系统性能产生
  • flask 文件 服务器,flask服务器文件上传云

    flask服务器文件上传云 内容精选 换一换 弹性云服务器支持通过内网访问OBS OBS可供用户存储任意类型的数据 将图片 视频等数据存储至OBS后 在ECS上可以访问OBS 下载桶中的图片或视频等数据 通过内网访问OBS 可以避免因网络不
  • ASP.NET中JSON的序列化和反序列化

    在项目开发过程中 发现需要用到JSON序列化 反序列化的问题 所有 在网上找到了一下这篇文章 摘录了下来 摘自 http www cnblogs com zhaozhan archive 2011 01 09 1931340 html JS
  • 使用ijkplayer播放4k视频卡顿的解决方法

    使用ijkplayer播放4k视频卡顿的解决方法 使用硬解码 ijkMediaPlayer setOption IjkMediaPlayer OPT CATEGORY PLAYER mediacodec 1
  • PAT甲级1135

    红黑树的特点 1 根节点是黑色 2 如果一个节点是红色那么他的两个子节点都是红色 3 任意从根节点到叶子结点的路径上 所有的路径经过的黑色节点数相同 4 红黑树是二叉搜索树 算法 1 根节点是否为黑色 2 红色节点的两个子节点是不是都是黑色
  • JS 数组或对象的遍历(for、for...in、for...of、foreach)

    转载自 JavaScript 比较for for in for of forEach的区别 非早起选手的博客 CSDN博客 目录 一 for 二 for in 三 for of 四 forEach 五 小结 一 for 最原始的方法 用来遍
  • 【在线教育】- 前端环境搭建&讲师CURD前端实现

    在线教育 一 在线教育前端环境搭建 1 1 vue element admin 概述 1 2 vue element admin master安装 1 3 vue element template介绍 了解 1 4 vue element
  • 牛客面试高频算法题js(输出二叉树的右视图、岛屿数量、矩阵的最小路径和、字符串出现次数的TopK问题、二叉树根节点到叶子节点的所有路径和)

    NC136 输出二叉树的右视图 描述 请根据二叉树的前序遍历 中序遍历恢复二叉树 并打印出二叉树的右视图 数据范围 0 le n le 100000 n 10000 要求 空间复杂度 O n O n 时间复杂度 O n O n 如输入 1
  • html跳转页面到自己写的另一个页面,非js

    最简单的跳转页面 记录给渣渣的自己 很low的两个html界面1和2 在1页面上设置一个button 按下按钮 跳转至自己写的2界面 代码如下 div class wrapper div class container h1 Welcome
  • Sqli-labs 15-19

    15关 在输入框内测试Username asd Password 123并点击提交后发现并没有什么卵用 在Username处尝试万能钥匙1 or 1 1 发现成功登录了 接下来看源码分析问题 由于红下划线处的username uname 所
  • 移动app开发如何做接口的版本控制

    移动app为什么要做版本控制 应用升级无法做到全部升级 比如某应用现行1 1版本 某次开发升级后 版本变为1 2 除app界面变化外 后台接口也发生了变化 然而不是所有的用户都在第一时间升级了app 或者由于版本推送不及时 用户忽略更新等原
  • 2020浙江大学软件学院预推免经验

    个人背景 本人为末流211计算机科学与技术专业 且专业排名于保研名额末尾 但是综合排名在中上肯定有保研资格 本科学校最后是以综合排名上报学信网的 而预推免和夏令营对方学校对看的一般是专业排名 预推免报名时本科学校已经出了推免名单了 所以预推
  • Datadog 能成为最大的云监控厂商吗

    Datadog 原本是一家名不见经传的云监控公司 于 2019年9月19日 登陆纳斯达克 上市首日即突破 80亿 美金 上市前还搞了个小插曲 思科在 IPO 前夕提出 70亿美元 全面收购要约 被 Datadog 董事会断然拒绝 时至今日
  • leetcode 55. 跳跃游戏

    一 题意 给定一个非负整数数组 nums 你最初位于数组的第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标 二 解法 贪心算法 解法1 计算出 i n u m s
  • Qt程序启动画面播放(gif与swf两种动画格式) - 路上的脚印

    学习Qt有一段时间了 发现一个小问题 网上关于Qt的资料或者总结性的学习及应用文章有点少 比如 Qt完整的API 程序运行之前的启动画面如何按理想效果播放等 每次想在项目中添加一些应用的时候 总是找不到好的书籍或文章可以马上学习 上手 今天
  • 淘宝、1688、京东、拼多多,抖音五个平台的区别分析

    淘宝 淘宝是中国最大的C2C电子商务平台 也是消费者购物的首选平台 淘宝上的商品种类繁多 价格实惠 同时还有很多优惠活动和促销活动 让消费者可以以较低的价格购买到高质量的商品 1688 1688是中国最大的批发市场之一 有数百万的商家在上面
  • Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件

    Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件 文章目录 Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件 一 Qt为release中可执行程序添
  • fedora11下gmlive0.22beta源代码安装

    1 解决依赖问题 否则会出现问题 No package gtkmm 2 4 found No package libglademm 2 4 found 安装依赖包 yum install gtkmm24 dev yum insttall l
  • C# 海康人脸识别设备初开发(二)话不多说以下完整例子

    demo截图 demo下载地址 https download csdn net download qq 16632449 11002228 以下完善了计划权限 可以参考下 其他的没了 如果提示错误23 基本是设备不支持 那你就要去问下海康的
  • Spring boot定时任务@Scheduled

    文章目录 1 前言 2 pom包配置 3 启动类启用定时 4 创建定时任务实现类 5 补充 cron表达式 6 遇到的坑 1 前言 Scheduled 参数可以接受两种定时的设置 一种是我们常用的cron 6 一种是 fixedRate 6