• Spring 配置 Quartz 定时器动态创建任务在修改任务后出现立即重复执行的情况


    Spring 配置 Quartz 定时器动态创建任务在修改任务后出现立即重复执行的情况

    前言

    在工作中有个专门去跑定时任务的小项目,它负责读取数据库配置的定时任务,然后生成相应的定时任务job进行执行,每1分钟读取一次,如果数据库中的定时任务有更新,则会重新加载执行。

    问题描述

    有一次需要将某个定时任务执行多次,于是想通过更改该定时任务的cron表达式,执行了一次后再增加时间修改cron表达式让它再次执行,但实践后发现定时任务在更改后程序读取到任务配置更新了就立即执行了,等到达设定时间后又再次执行了一次,相当于更新后执行了2次,但我们想要的是让它按照我们设定的时间执行,而不是更新后立即执行。

    分析与解决方案

    MisfireInstruction

    trigger中有一个MisfireInstruction的属性,这个属性是用来控制定时器错过时间后是否还要继续执行。

    misfireInstruction的数据类型为int

    MISFIRE_INSTRUCTION_SMART_POLICY = 0

    misfireInstruction的默认值就是该值

    MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1

    错过任务后立即执行1次

    MISFIRE_INSTRUCTION_DO_NOTHING = 2

    错过任务后不执行已错过的任务,只执行当前的

    上述遇到的问题就是这个属性导致的,因为默认情况下,定时器错过执行时间后会立即补救执行一次上一次没执行的任务,然后再执行当前这一次时间的任务,所以上面的问题才会执行2次,因为修改cron表达式后,定时器发现上一次没有执行,于是就立即执行了一遍,然后再执行当前这次的任务。

    解决方法

    方法1

    由于我只是想要执行完定时任务后再修改时间让它再次执行,为了不再被定时器发现上一次没有执行,可以加上当前的日期。

    cron表达式修改前

    0 20 14 * * ?
    

    cron表达式修改后

    0 20 14 24 4 ? 2022
    

    这样精确设置时候后就不会在定时任务修改后出现立即执行的情况了

    方法2

    修改msifireinstruction值,修改为MISFIRE_INSTRUCTION_DO_NOTHING=2

    c.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
    

    示例代码

    启动

    执行MainStart类下的main方法

    问题复现

    启动执行5分钟后,修改cron.txt文件的cron表达式,改为启动时间到当前时间这五分钟内的时间,等待程序检测到任务更新后即可复现

    例如:MainStart启动时间为10:20,五分钟后就是10:25,然后修改cron表达式为0 22 10 * * ?即可发现在更新任务后立即执行了任务一次

    示例代码:https://gitee.com/welitis/blog_code/tree/master/SpringQuartzRepeatExe

    参考

    Quartz框架(四)—misfire处理机制 - 简书 (jianshu.com)

    Spring中配置Quartz的misfireInstruction_george_hsu的博客-CSDN博客

    Quartz 定时器动态创建任务和修改执行时间修改后出现立即执行情况_liufei198613的博客-CSDN博客

  • 相关阅读:
    TCP/IP协议栈与数据包封装+TCP与UDP区别
    MySQL数据库优化总结
    MySQL存储引擎,锁,优化简述
    java实现常见查找算法
    Java的几种常见排序算法
    UML类图学习
    高性能的RTC服务器OpenFire
    常用的设计模式
    Swing JInternalFrame的使用
    Qt 模态与非模态
  • 原文地址:https://www.cnblogs.com/welisit/p/16185641.html
Copyright © 2020-2023  润新知