SpringBoot中定时任务踩坑,@Scheduled重复执行问题排查(看完直接破防)

在这里插入图片描述

前言

今天再开发业务需求的过程中,需要用到定时任务,原本定的是每10分钟推送一次,可是当每次十分钟到的时候,定时任务就会推送多条!但是非常奇怪的是,本地调试的时候不会有问题,只有当你部署到到服务器上的时候才会暴露这个问题!!!!

如图:

这些消息都是一次性推送出来的,本来他们应该只有一条被推送出来的,可是现在他们却全都出来了,难道真是“一家人就要整整齐齐”吗?

解决思路

这种本地无法重现的问题解决起来最恼火了,于是乎我去网上寻找答案,看看有没有人遇到类似的情况!
其中两篇是这么说的:

文章连接:生产问题:@Scheduled Spring定时任务每次执行两次原因分析以及解决方案

文章连接:spring定时任务执行两次的原因与解决方法

他们的大概的意思就是因为他的配置到导致他的配置类被重复加载了两次,进而导致定时任务重复执行多次!

于是我就类比了一下,看到在我的项目中,确实使用了@EnableScheduling两次

第一次:

第二次:

于是我赶紧把启动类上的@EnableScheduling注解去掉,并祈祷能有用!

结果如我所料,果然没什么用!

于是我继续搜索,看到这样一篇文章:


当我看到这句话的时候,我甚至以为我已经接近真理了!
springboot关于定时任务执行多次的问题
但是当我看到他写的这些太乱了,而且一个简答的定时任务,被他搞得这么复杂,我果断放弃了。

头痛砍头????

我于是乎又接着找,我发现了这样一篇文章,特别逆天!!!


Springboot 使用 @Scheduled 定时任务生产环境执行两次

好家伙,你这好比你去医院看病,你和医生说:”医生我头痛,我该怎么办?“,医生说:”没事的哈,一会去把把头砍了,砍了就不痛了哈!“

接近真理

时间在一分一秒的过去,我却毫无紧张,甚至已经开始汗流浃背了,从未感到如此巨大之强度,于是乎我便去到了stackoverflow上搜索一下看看!

哎!你说好巧不巧,还真就让我找到问题了!
看到这样一条问题:


这不就是我遇到的问题吗?

他是这么说的:

I have a service which has to run a job to get and refresh it's data from another service. The job has to be run on startup and every couple of hours/days. I was looking into the behavior of the scheduled job and it seems to be called two times consecutively according to the logs (see below).

我们来看他给的代码:

@Service
public class ServiceImpl implements ServiceInterface {

@Autowired
private FetchService fetchService;

private int timesCalled = 0;
private Data data;

@PostConstruct
private void initialize() {
    data = fetchService.getAndUpdate();
}

@Scheduled(cron = "* */5 * * * *")
private void refresh() {
    LOG.info(appContext.getId());
    LOG.info("This object: " + System.identityHashCode(this));
    LOG.info("Times called: " +  timesCalled);
    timesCalled++;
    data = fetchService.getAndUpdate();
}

日志信息:

2020-07-02 17:30:00.006  INFO 30416 --- [   scheduling-1] c.d.p.d.service.ServiceImpl  : org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6db9cae5
2020-07-02 17:30:00.006  INFO 30416 --- [   scheduling-1] c.d.p.d.serice.ServiceImpl  : This object: 357813323
2020-07-02 17:30:00.006  INFO 30416 --- [   scheduling-1] c.d.p.d.service.ServiceImpl  : Times called: 1
....
2020-07-02 17:30:32.001  INFO 30416 --- [   scheduling-1] c.d.p.d.service.ServiceImpl  : org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6db9cae5
2020-07-02 17:30:32.001  INFO 30416 --- [   scheduling-1] c.d.p.d.service.ServiceImpl  : This object: 357813323
2020-07-02 17:30:32.001  INFO 30416 --- [   scheduling-1] c.d.p.d.service.ServiceImpl  : Times called: 2

然后就有网友给他解释道:正如你所写的,你的cron表达式是 * */5 * * * * ,这意味着,根据Spring指南,它将每隔5分钟运行一次:

你写的代码不就是下面这样吗?

@Scheduled(cron = "* */5 * * * *")
private void refresh() {
    log.info("Times called: " +  timesCalled);
    timesCalled++;
}

我们来测试一下吧:

14:20:13.001  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 13
14:20:14.001  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 14
14:20:15.003  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 15
14:20:59.002  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 59
14:25:00.000  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 60
14:25:01.000  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 61
14:25:02.001  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 62
14:25:03.002  INFO 8980 --- [   sch-1] com.example.demo.Sched   : Times called: 63

从日志我们可以看出,他确实是在每五分钟执行一次,可是执行完了,他在第五分钟内还将重复执行!所以我们会看到业务代码被执行了很多次!如果你想每五分钟只执行一次的话,你应该这样写:@Scheduled(cron = "0 */5 * * * *")

成功解救

我一看我的代码也是这样写的:


赶紧改过来,问题就解决了!这下对spring的corn表达式理解又加深了!同时有问题可去stackoverflow上搜一下,很有用!!

最后的疑问

为什么本地调试我0 */5 * * * *这样写和* */5 * * * *都只执行一次,而到线上的时候就会执行多次,有谁能知道这是为什么?

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV | 图像读取与显示

OpenCV 对图像进行处理时,常用API如下: API描述cv.imread根据给定的磁盘路径加载对应的图像,默认使用BGR方式加载cv.imshow展示图像cv.imwrite将图像保存到磁盘中cv.waitKey暂停一段时间,接受键盘输出后,继续执行程序…

windows 之 redis非安装版,启动与初始化密码

1、下载redis 免安装版 2、解压后,启动服务 3、双击客服端 4、设置密码 config set requirepass root123456成功后,退出服务再次双击 5、登录 再次执行命名时已经没权限了 使用 auth password 登录 成功后,就可以了 auth root123456 …

arcgis使用面shp文件裁剪线shp文件报错

水系数据裁剪,输出为空: ArcGIS必会的几个工具的应用 --提取、分割、融合、裁剪(矢)、合并、追加、镶嵌、裁剪(栅)、重采样_arcgis分割-CSDN博客 下面的方法都不行: ArcGIS Clip(裁…

JavaScript - 你遇到过哪几种Javascript的错误类型

难度级别:中级及以上 提问概率:50% 我们在开发Javascript代码的时候,经常一不小心就会遇到各种各样的异常,浏览器也会及时给出错误信息,那么一般会遇到哪几种异常情况呢,我们来看一下。 1 ReferenceError错误 ReferenceError几乎是最…

Ubuntu 20.04.06 PCL C++学习记录(二十四)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16,可用点云下载地址 学习内容 如何使用已知系数的 SAC_Models 从点云中提取参数模型…

Tomcat 获取客户端真实IP X-Forwarded-For

Tomcat 获取客户端真实IP X-Forwarded-For 代码实现&#xff1a; 在Host标签下面添加代码&#xff1a; <Valve className"org.apache.catalina.valves.RemoteIpValve" remoteIpHeader"x-forwarded-for" remoteIpProxiesHeader"x-forwarded-by&q…

面试算法-165-随机链表的复制

题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节…

网络安全---非对称数据加密签名验证

一、课题描述 三位同学一组完成数据的非对称加密和数字签名验证传输。 三位同学分别扮演图中 Alice、Bob 和 CA 三个角色&#xff0c;Bob 和 Alice 从 CA 中获得数字证书、Bob 向 Alice 发送秘密发送一段加密并签名后的信息&#xff0c;Alice 获取 Bob 发送的加密信息&#x…

关于ARM的一些问题

一&#xff0c;arm的工作模式有哪些&#xff1f; User&#xff1a;非特权模式 FIQ&#xff1a;高优先级中断进入 IRQ&#xff1a;低优先级中断进入 Supervisor:当复位或软中断指令进入 Abort: 当存取异常时 Undef:当执行未定义指令时会进入这种模式 System:使用和User模式相同…

科技云报道:从“奇点”到“大爆炸”,生成式AI开启“十年周期”

科技云报道原创。 世界是复杂的&#xff0c;没有人知道未来会怎样&#xff0c;但如果单纯从技术的角度&#xff0c;我们总是能够沿着技术发展的路径&#xff0c;找到一些主导未来趋势的脉络。 从Sora到Suno&#xff0c;从OpenAI到Copilot、Blackwell&#xff0c;这些热词在大…

【Redis】底层跳表实现

先巩固Redis的数据类型以及底层的数据结构&#xff1a; ZSet&#xff08;有序集合&#xff09;可以使用两种不同的内部数据结构来表示&#xff1a;压缩列表&#xff08;ziplist&#xff09;和跳跃表&#xff08;skiplist&#xff09;。 跳表是redis底层SortedSet(ZSet)的数据…

JAVA并发编程(二)_线程池

JAVA线程池 1.1Java 线程池之 Executor 框架 为了实现线程池和管理线程池&#xff0c;JDK 给我们提供了基于 Executor 接口的一系列接口、抽象类、实现类&#xff0c;我们把它称作线程池的 Executor 框架&#xff0c;Executor 框架本质上是一个线程池&#xff1b; ​ Java 线…

Linux LVM磁盘扩容

1、查看磁盘情况 df -h df -h2、查看逻辑卷 lvdisplay lvdisplay3、查看逻辑组 vgdisplay vgdisplay4、查看物理卷 pvdisplay pvdisplay5、查看磁盘 fdisk -l fdisk -l6、磁盘分区fdisk /dev/磁盘名 # 上一步查看到的新硬盘路径 fdisk /dev/vdb7、格式化磁盘mkfs -t ext4…

【负载均衡——一致性哈希算法】

1.一致性哈希是什么 一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时&#xff0c;发生过多的数据迁移的问题。 一致哈希算法也用了取模运算&#xff0c;但与哈希算法不同的是&#xff0c;哈希算法是对节点的数量进行取模运算&#xff0c;而一致哈希算法是对 2^32 进…

基于SSM+Jsp+Mysql的超市管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

图片管理系统:原理、设计与实践

title: 图片管理系统&#xff1a;原理、设计与实践 date: 2024/4/9 20:04:25 updated: 2024/4/9 20:04:25 tags: 图片管理存储组织上传采集处理编辑搜索检索展示分享AI应用 第一章&#xff1a;图片管理系统概述 1.1 图片管理系统简介 图片管理系统是一种用于存储、组织、处理…

【Java网络编程】IP网络协议与TCP、UDP网络传输层协议

1.1、IP协议 当应用层的数据被封装后&#xff0c;想要将数据在网络上传输&#xff0c;数据究竟要被发往何处&#xff0c;又该如何精准的在网络上定位目标机器&#xff0c;此时起到关键作用的就是“IP协议”。IP协议的作用在于把各种数据包准确无误的传递给目标方&#xff0c;其…

力扣HOT100 - 56. 合并区间

解题思路&#xff1a; class Solution {public int[][] merge(int[][] intervals) {// 先按照区间起始位置排序Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);int[][] res new int[intervals.length][2];int idx -1;for (int[] interval : intervals) {//直接加入的…

前端实现打开新标签页后,再次定位到该标签页

需求 A 页面中点击按钮可以打开新的标签页 B 并且向 B 页面发送消息数据。 当新的标签页 B 未关闭且符合同源策略时&#xff0c;再次点击按钮&#xff0c;可以自动跳转到标签页 B 并且发生消息数据。 B.html <script>window.onmessage evt > {console.log(evt.d…

wps的1)2)3)编号,怎么更新

全部选中->格式刷->把它刷了必须全部选中