精进Quartz源码—Quartz调度器的Misfire处理规则(四)[通俗易懂]

Quartz调度器的Misfire处理规则调度器的启动和恢复中使用的misfire机制,还需细化!

大家好,又见面了,我是全栈君。

=================================================

对人工智能感兴趣的伙伴,分享一个我朋友的人工智能教程。零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助,点击这里查看教程

=================================================

欢迎关注我的公众号: Java编程技术乐园。分享技术,一起精进Quartz!

做一个积极的人

编码、改bug、提升自己

我有一个乐园,面向编程,春暖花开!

Quartz调度器的Misfire处理规则

调度器的启动和恢复中使用的misfire机制,还需细化!


一、SimpleTrigger的misfire机制 默认的 Trigger.MISFIRE_INSTRUCTION_SMART_POLICY !!!

trig.updateAfterMisfire(cal);
getMisfireInstruction() —-> misfireInstruction == 0
——以当前时间为触发频率立即触发执行

SimpleScheduleBuilder ssb = SimpleScheduleBuilder.simpleSchedule();

ssb.withMisfireHandlingInstructionFireNow();//1
ssb.withMisfireHandlingInstructionIgnoreMisfires();//2
ssb.withMisfireHandlingInstructionNextWithExistingCount();//3
ssb.withMisfireHandlingInstructionNextWithRemainingCount();//4
ssb.withMisfireHandlingInstructionNowWithExistingCount();//5
ssb.withMisfireHandlingInstructionNowWithRemainingCount();//6
//1
withMisfireHandlingInstructionFireNow  ---> misfireInstruction == 1
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值

//2
withMisfireHandlingInstructionIgnoreMisfires ---> misfireInstruction == -1
—以错过的第一个频率时间立刻开始执行
——重做错过的所有频率周期
——当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率
——共执行RepeatCount+1
//3
withMisfireHandlingInstructionNextWithExistingCount ---> misfireInstruction == 5
——不触发立即执行
——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
——以startTime为基准计算周期频率,并得到FinalTime
——即使中间出现pause,resume以后保持FinalTime时间不变
//4
withMisfireHandlingInstructionNextWithRemainingCount ---> misfireInstruction = 4
——不触发立即执行
——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
——以startTime为基准计算周期频率,并得到FinalTime
——即使中间出现pause,resume以后保持FinalTime时间不变
//5
withMisfireHandlingInstructionNowWithExistingCount ---> misfireInstruction = 2
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
//6
withMisfireHandlingInstructionNowWithRemainingCount --- >misfireInstruction = 3
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值


MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT 值为 3
——此指令导致trigger忘记原始设置的starttime和repeat-count
——触发器的repeat-count将被设置为剩余的次数
——这样会导致后面无法获得原始设定的starttime和repeat-count值

updateAfterMisfire 方法源码:

/** * <p> * Updates the <code>SimpleTrigger</code>'s state based on the * MISFIRE_INSTRUCTION_XXX that was selected when the <code>SimpleTrigger</code> * was created. * </p> * * <p> * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, * then the following scheme will be used: <br> * <ul> * <li>If the Repeat Count is <code>0</code>, then the instruction will * be interpreted as <code>MISFIRE_INSTRUCTION_FIRE_NOW</code>.</li> * <li>If the Repeat Count is <code>REPEAT_INDEFINITELY</code>, then * the instruction will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT</code>. * <b>WARNING:</b> using MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT * with a trigger that has a non-null end-time may cause the trigger to * never fire again if the end-time arrived during the misfire time span. * </li> * <li>If the Repeat Count is <code>&gt; 0</code>, then the instruction * will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>. * </li> * </ul> * </p> * */
/* 基于在创建SimpleTrigger时选择的MISFIRE_INSTRUCTION_XXX更新SimpleTrigger的状态。 如果失火指令设置为MISFIRE_INSTRUCTION_SMART_POLICY,则将使用以下方案: •如果重复计数为0,则指令将解释为MISFIRE_INSTRUCTION_FIRE_NOW。 •如果重复计数为REPEAT_INDEFINITELY,则指令将解释为MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT。 警告:如果触发器具有非空的结束时间,则使用MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT可能会导致触发器在失火时间范围内到达结束时,不会再次触发。 •如果重复计数大于0,则指令将解释为MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT。 */
@Override
public void updateAfterMisfire(Calendar cal) { 
   
    int instr = getMisfireInstruction();//获取misfire的值,默认为0

    if(instr == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY)//instr == -1
        return;

    if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) { 
    //instr == 1
        if (getRepeatCount() == 0) { 
   
            instr = MISFIRE_INSTRUCTION_FIRE_NOW; //instr = 1
        } else if (getRepeatCount() == REPEAT_INDEFINITELY) { 
   //getRe..Count == -1
            //instr = 4
            instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
        } else { 
   
            // if (getRepeatCount() > 0)
            instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;//instr == 2
        }
        //instr == 1
    } else if (instr == MISFIRE_INSTRUCTION_FIRE_NOW && getRepeatCount() != 0) { 
   
        //instr == 3
        instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT;
    }

    if (instr == MISFIRE_INSTRUCTION_FIRE_NOW) { 
    //instr == 1
        setNextFireTime(new Date());
        //instr == 5
    } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) { 
   
        Date newFireTime = getFireTimeAfter(new Date());
        while (newFireTime != null && cal != null
               && !cal.isTimeIncluded(newFireTime.getTime())) { 
   
            newFireTime = getFireTimeAfter(newFireTime);

            if(newFireTime == null)
                break;

            //avoid infinite loop
            java.util.Calendar c = java.util.Calendar.getInstance();
            c.setTime(newFireTime);
            if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { 
   
                newFireTime = null;
            }
        }
        setNextFireTime(newFireTime);
        //instr == 4
    } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT) { 
   
        Date newFireTime = getFireTimeAfter(new Date());
        while (newFireTime != null && cal != null
               && !cal.isTimeIncluded(newFireTime.getTime())) { 
   
            newFireTime = getFireTimeAfter(newFireTime);

            if(newFireTime == null)
                break;

            //avoid infinite loop
            java.util.Calendar c = java.util.Calendar.getInstance();
            c.setTime(newFireTime);
            if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { 
   
                newFireTime = null;
            }
        }
        if (newFireTime != null) { 
   
            int timesMissed = computeNumTimesFiredBetween(nextFireTime,
                                                          newFireTime);
            setTimesTriggered(getTimesTriggered() + timesMissed);
        }

        setNextFireTime(newFireTime);
    } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT) { 
    //instr == 2
        Date newFireTime = new Date();
        if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { 
   
            setRepeatCount(getRepeatCount() - getTimesTriggered());
            setTimesTriggered(0);
        }

        if (getEndTime() != null && getEndTime().before(newFireTime)) { 
   
            setNextFireTime(null); // We are past the end time
        } else { 
   
            setStartTime(newFireTime);
            setNextFireTime(newFireTime);
        } 
    } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT) { 
    //instr == 3
        Date newFireTime = new Date();

        int timesMissed = computeNumTimesFiredBetween(nextFireTime,
                                                      newFireTime);

        if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { 
    //repeatCount == -1
            int remainingCount = getRepeatCount()
                - (getTimesTriggered() + timesMissed);
            if (remainingCount <= 0) { 
    
                remainingCount = 0;
            }
            setRepeatCount(remainingCount);
            setTimesTriggered(0);
        }

        if (getEndTime() != null && getEndTime().before(newFireTime)) { 
   
            setNextFireTime(null); // We are past the end time
        } else { 
   
            setStartTime(newFireTime);
            setNextFireTime(newFireTime);
        } 
    }

}

二、CronTrigger的misfire机制—-默认的 Trigger.MISFIRE_INSTRUCTION_SMART_POLICY !!!

trig.updateAfterMisfire(cal);
getMisfireInstruction() —-> misfireInstruction == 0

CronScheduleBuilder csb = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
				
csb.withMisfireHandlingInstructionDoNothing();
csb.withMisfireHandlingInstructionFireAndProceed();
csb.withMisfireHandlingInstructionIgnoreMisfires();
withMisfireHandlingInstructionDoNothing ---> misfireInstruction = 2
——不触发立即执行
——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
withMisfireHandlingInstructionFireAndProceed ---> misfireInstruction = 1
——以当前时间为触发频率立刻触发一次执行
——然后按照Cron频率依次执行

withMisfireHandlingInstructionIgnoreMisfires ---> misfireInstruction = -1
——以错过的第一个频率时间立刻开始执行
——重做错过的所有频率周期后
——当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行

updateAfterMisfire 方法源码:

/** * <p> * Updates the <code>CronTrigger</code>'s state based on the * MISFIRE_INSTRUCTION_XXX that was selected when the <code>CronTrigger</code> * was created. * </p> * * <p> * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, * then the following scheme will be used: <br> * <ul> * <li>The instruction will be interpreted as <code>MISFIRE_INSTRUCTION_FIRE_ONCE_NOW</code> * </ul> * </p> */
/* 根据创建CronTrigger时选择的MISFIRE_INSTRUCTION_XXX更新CronTrigger的状态。 如果失火指令设置为MISFIRE_INSTRUCTION_SMART_POLICY,则将使用以下方案: •指令将解释为MISFIRE_INSTRUCTION_FIRE_ONCE_NOW */

@Override
public void updateAfterMisfire(org.quartz.Calendar cal) { 
   
    int instr = getMisfireInstruction();//获取misfire的值,默认为0

    if(instr == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY)//instr == -1
        return;

    if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) { 
   //instr == 0
        instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;//instr = 1
    }

    if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) { 
   //instr == 2
        Date newFireTime = getFireTimeAfter(new Date());
        while (newFireTime != null && cal != null
               && !cal.isTimeIncluded(newFireTime.getTime())) { 
   
            newFireTime = getFireTimeAfter(newFireTime);
        }
        setNextFireTime(newFireTime);
    } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) { 
   //instr == 1
        setNextFireTime(new Date());
    }
}

参考文章

Quartz的Misfire处理规则
Quartz-错过触发机制

Quartz专栏系列

1.精进Quartz——Quartz大致介绍(一)
2.精进Quartz——Quartz简单入门Demo(二)
3.精进Quartz——Spring和Quartz集成详解
4.精进Quartz——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(四)
5.精进Quartz源码——JobStore保存JonDetail和Trigger源码分析(一)
6.精进Quartz源码——scheduler.start()启动源码分析(二)
7.精进Quartz源码——QuartzSchedulerThread.run() 源码分析(三)
8.精进Quartz源码——Quartz调度器的Misfire处理规则(四)http://blog.csdn.net/u010648555/article/details/53672738)


谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你每天开心愉快!


不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

博客首页 : http://blog.csdn.net/u010648555

愿你我在人生的路上能都变成最好的自己,能够成为一个独挡一面的人
精进Quartz源码—Quartz调度器的Misfire处理规则(四)[通俗易懂]

© 每天都在变得更好的阿飞云

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/121200.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 恶搞代码——vbs进程

    今天跟大家分享一下娱乐的恶搞代码,想必很多人也知道,那么针对电脑小白来说可能就不是非常清楚了,其实过程也很简单,那么下面就是其中比较常见的恶搞源码:一.电脑语音恶搞:首先我们先新建一个后缀为txt的记事本文档,如下图:然后将下面的代码复制到新建的文本文档中:CreateObject(“SAPI.SpVoice”).Speak”你的电脑接收到了一个自爆程序,电脑即将爆炸,请您在15秒时间内…

    2022年4月8日
    1.7K
  • OpenSSL密码库算法笔记——第5.1.1章 椭圆曲线点群的定义

    OpenSSL密码库算法笔记——第5.1.1章 椭圆曲线点群的定义下面定义的椭圆曲线点群不仅包含了域的信息和曲线的信息,甚至还包括了很多别的有利于实现的信息。椭圆曲线点群的定义如下。typedefstructec_group_stEC_GROUP;structec_group_st{constEC_METHOD*meth;EC_POINT*generator;BIGNUM…

    2022年7月20日
    19
  • 如何用51单片机控制步进电机运动「建议收藏」

    如何用51单片机控制步进电机运动「建议收藏」本来接触单片机挺久了的,但是一直只是停留在非常初级的认识阶段,本科的时候上过几门课,但是从来没有自己捣鼓过单片机,这次突然来了兴趣,感觉一下子学到了好多东西,在这里好好整理一下。这篇文章只适合于入门阶段的小白阅读,高手请绕道。12年年初的时候购买了一套普中科技的“单片机开发试验仪”,好多次想好好学学,结果每一次都半途而废,主要原因还是周围的人都不会用,有问题都不知道找谁问,结果锁到箱子里一直到现在。

    2022年6月1日
    33
  • Advanced SystemCare激活

    Advanced SystemCare激活AdvancedSystemCare6.x(x>=1)激活方案 1,请先在电脑上安装6.0版本。输入以下激活码激活:注册码:4A639-FD966-C5435-512C4[使用6.0版本用以上注册码可以激活]更多注册码CC52B-28CB1-DAF12-A96D6 65792-57FC4-5CEC1-677C4 4A639-FD966-C5435-512C

    2022年10月20日
    0
  • Avro介绍[通俗易懂]

    Avro介绍[通俗易懂]ApacheAvro是一个数据序列化系统。Avro所提供的属性:1.丰富的数据结构2.使用快速的压缩二进制数据格式3.提供容器文件用于持久化数据4.远程过程调用RPC5.简单的动态语言结合功能,Avro和动态语言结合后,读写数据文件和使用RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现。Avro的SchemaAvro的Schema用…

    2025年5月23日
    2
  • pycharm代码规范工具flake8

    pycharm代码规范工具flake8文章目录代码规范一、flake8是什么?二、使用步骤1.引入库2.读入数据总结代码规范随着计算机语言的发展,代码规范是我们写代码时更应该注意的东西,在我们使用pycharm进行代码编写时,我们可以借用pycharm工具flake8进行代码规范检查,从而使代码规范符合标准要求。代码规范可以减少bug,有助于代码审查,降低维护成本,更重要的是在大型项目中,大家使用一套共同的代码标准,这更能够提升团队间的合作效率。一、flake8是什么?Flake8是一款辅助检测Python代码是否规范的工具

    2022年9月4日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号