• 后端——框架——定时任务——quartz——Trigger


      本篇介绍Trigger, 它是顶层接口,Trigger的类结构如下:

      

       MutableTrigger是状态可变的触发器,不单独使用,所有Trigger都继承此接口。

    CoreTrigger存在额外属性的触发器,只有一个方法hasAddtionalProperties。不单独使用,所有Trigger都继承此接口。

    CalendarIntervalTrigger:根据日期,间隔触发,日期中只包含年,月,日,间隔的单位也只有年,月,日。

    DailyTimeIntervalTrigger: 根据日期,间隔触发,日期中只包含时,分,秒,间隔的单位也只有时,分,秒。

    SimpleTrigger根据日期,间隔触发,日期中包含年,月,日,时,分,秒。

    CronTrigger根据Cron表达式触发。

    经常使用的只有两种,SimpleTrigger和CronTrigger。

    除上述对象之外,Trigger相关的对象与Job相关的对象相似,也有TriggerBuilder,TriggerKey,TriggerDataMap, TriggerListener。

    1、属性

    @SuppressWarnings("unchecked")
    public T build() {
    
        if(scheduleBuilder == null)
            scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
        MutableTrigger trig = scheduleBuilder.build();
        
        trig.setCalendarName(calendarName);
        trig.setDescription(description);
        trig.setStartTime(startTime);
        trig.setEndTime(endTime);
        if(key == null)
            key = new TriggerKey(Key.createUniqueName(null), null);
        trig.setKey(key); 
        if(jobKey != null)
            trig.setJobKey(jobKey);
            trig.setPriority(priority);
        
        if(!jobDataMap.isEmpty())
            trig.setJobDataMap(jobDataMap);
        
        return (T) trig;
    }
    

      calendarName:Calendar对象的唯一标识。排除特定时间,参考Calendar对象。

      description:Trigger的描述信息。

    startTime:Trigger触发的开始时间。它不是任务真正的开始时间。

    endTime:Trigger触发的结束时间。它不是任务真正的结束时间。

    triggerKey:Trigger的唯一标识,名称和组。

    triggerDataMap:与JobDataMap基本相同。

    priority:Trigger的优先级。

    2、 SimpleTrigger

    SimpleTrigger的知识点有两个,设置SimpleTrigger的属性,它的Mis_fire策略。

    2.1    设置属性

    设置属性是通过调用TriggerBuilder的相关方法。

    TriggerKey:调用withIdentity方法,第一个参数表示name,第二个参数表示group。

    startTime:调用startAt方法,参数为date。也可以调用startNow。

    间隔:调用withScheduler方法,参数为ScheduleBuilder,它有实现类XXScheduleBuilder,每个实现类中都有withIntervalXXX,后面的XXX代表的是间隔的时间单位,方法的参数代表间隔的时间值。

    重复次数:调用withRepeatCount方法,参数为其值。调用repeatForever无限重复。

    endTime:调用endAt方法。

    关联Job:调用forJob方法。

    2.2    MisFire

    当SimpleTrigger未被正常触发之后,有以下六种策略。

      MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY

    /**
     * Instructs the <code>{@link Scheduler}</code> that the 
     * <code>Trigger</code> will never be evaluated for a misfire situation, 
     * and that the scheduler will simply try to fire it as soon as it can, 
     * and then update the Trigger as if it had fired at the proper time. 
     * 
     * <p>NOTE: if a trigger uses this instruction, and it has missed 
     * several of its scheduled firings, then several rapid firings may occur 
     * as the trigger attempt to catch back up to where it would have been. 
     * For example, a SimpleTrigger that fires every 15 seconds which has 
     * misfired for 5 minutes will fire 20 times once it gets the chance to 
     * fire.</p>
     */
    public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;
    

      快速的执行任务(重复次数相同),忽略开始时间,间隔,结束时间。不能用于无限重复的触发器。

      MISFIRE_INSTRUCTION_FIRE_NOW

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link SimpleTrigger}</code> wants to be fired
     * now by <code>Scheduler</code>.
     * </p>
     * 
     * <p>
     * <i>NOTE:</i> This instruction should typically only be used for
     * 'one-shot' (non-repeating) Triggers. If it is used on a trigger with a
     * repeat count > 0 then it is equivalent to the instruction <code>{@link #MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT}
     * </code>.
     * </p>
     */
    

      在now执行一次,之后将now作为开始时间,间隔不变,重复次数为剩余的重复次数

      MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link SimpleTrigger}</code> wants to be
     * re-scheduled to 'now' (even if the associated <code>{@link Calendar}</code>
     * excludes 'now') with the repeat count left as-is.  This does obey the
     * <code>Trigger</code> end-time however, so if 'now' is after the
     * end-time the <code>Trigger</code> will not fire again.
     * </p>
     * 
     * <p>
     * <i>NOTE:</i> Use of this instruction causes the trigger to 'forget'
     * the start-time and repeat-count that it was originally setup with (this
     * is only an issue if you for some reason wanted to be able to tell what
     * the original values were at some later time).
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2;
    

      将now作为开始时间,间隔不变,重复次数为剩余的重复次数,它受结束时间的约束,当到达结束时间时,任务不会在执行,当now大于结束时间时,任务不会执行

      MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link SimpleTrigger}</code> wants to be
     * re-scheduled to 'now' (even if the associated <code>{@link Calendar}</code>
     * excludes 'now') with the repeat count set to what it would be, if it had
     * not missed any firings.  This does obey the <code>Trigger</code> end-time 
     * however, so if 'now' is after the end-time the <code>Trigger</code> will 
     * not fire again.
     * </p>
     * 
     * <p>
     * <i>NOTE:</i> Use of this instruction causes the trigger to 'forget'
     * the start-time and repeat-count that it was originally setup with.
     * Instead, the repeat count on the trigger will be changed to whatever
     * the remaining repeat count is (this is only an issue if you for some
     * reason wanted to be able to tell what the original values were at some
     * later time).
     * </p>
     * 
     * <p>
     * <i>NOTE:</i> This instruction could cause the <code>Trigger</code>
     * to go to the 'COMPLETE' state after firing 'now', if all the
     * repeat-fire-times where missed.
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3;
    

      将now作为开始时间,间隔不变,重复次数为剩余的重复次数,与EXISTING的区别在于它不受结束时间的约束

      MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link SimpleTrigger}</code> wants to be
     * re-scheduled to the next scheduled time after 'now' - taking into
     * account any associated <code>{@link Calendar}</code>, and with the
     * repeat count set to what it would be, if it had not missed any firings.
     * </p>
     * 
     * <p>
     * <i>NOTE/WARNING:</i> This instruction could cause the <code>Trigger</code>
     * to go directly to the 'COMPLETE' state if all fire-times where missed.
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4;
    

      与NOW的区别是它不改变开始时间,根据原始任务的开始时间,间隔计算下次的触发时间。不受结束时间的约束

      MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link SimpleTrigger}</code> wants to be
     * re-scheduled to the next scheduled time after 'now' - taking into
     * account any associated <code>{@link Calendar}</code>, and with the
     * repeat count left unchanged.
     * </p>
     * 
     * <p>
     * <i>NOTE/WARNING:</i> This instruction could cause the <code>Trigger</code>
     * to go directly to the 'COMPLETE' state if the end-time of the trigger
     * has arrived.
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5;
    

      与NOW的区别是它不改变开始时间,与REMAINING的区别是它受到时间状态的约束

    3、CronTrigger

    CronTrigger的知识点有三个,设置属性,Cron表达式,MisFire策略。

    3.1     设置属性

    TriggerKey:调用withIdentity方法,第一个参数为名称,第二个参数为组。

    Cron表达式:调用withScheduler方法,参数为ScheduleBuilder,CronScheduleBuilder为其实现类之一。调用CronScheduleBuilder的cronSchedule方法,参数为cron表达式。

    timezone:调用withScheduler方法,参数为ScheduleBuilder,CronScheduleBuilder为其实现类之一。调用CronScheduleBuilder的inTimeZone方法,参数为TimeZone对象。

    3.2     Cron表达式

    Cron表达式的格式有七部分组成。分别是:

    秒 分钟 小时  天(某月的一天) 月  周 年

    下面具体分析每个部分的格式

    3.2.1   秒

    格式

    num ,— * /

    允许值

    0-59

    是否必填

    示例

    单个数值形式,例如0 表示在第0秒执行

    多个数值形式(逗号),例如0,15,20  表示在第0秒,15秒,20秒执行

    数值范围形式(横杠),例如0-15  表示在0-15秒之间每一秒都执行一次

    数值递增形式(斜杠),例如3/15 其中3表示初始值,15表示递增值,表示在3,18, 43 ,58秒执行

    任意值(通配符),例如 * 表示每秒执行一次,这个通常不适用

    3.2.2   分钟

    与秒的格式基本相同

    格式

    num ,— * /

    允许值

    0-59

    是否必填

    示例

    单个数值形式,例如0 表示在第0分钟执行

    多个数值形式(逗号),例如0,15,20  表示在第0分,15分,20分执行

    数值范围形式(横杠),例如0-15  表示在0-15分之间每一分都执行一次

    数值递增形式(斜杠),例如3/15 其中3表示初始值,15表示递增值,表示在3,18, 43 ,58分执行

    任意值(通配符),例如 * 表示每分执行一次

      3.2.3  小时

    与秒,分钟的格式基本相同

    格式

    num ,— * /

    允许值

    0-59

    是否必填

    示例

    单个数值形式,例如0 表示在第0小时执行

    多个数值形式(逗号),例如0,15,20  表示在第0时,15时,20时执行

    数值范围形式(横杠),例如0-15  表示在0-15时之间每一小时执行一次

    数值递增形式(斜杠),例如3/15 其中3表示初始值,15表示递增值,表示在3,18, 43 ,58小时执行

    任意值(通配符),例如 * 表示每小时执行一次

      3.2.4      天

    表示当前月的某一天

    格式

    num ,— * / ? L W

    允许值

    1-31

    是否必填

    示例

    单个数值形式,例如1 表示在每月的第一天执行

     

    多个数值形式(逗号),例如1,15,20  表示在第1号,15号,20号执行

     

    数值范围形式(横杠),例如0-15  表示在0-15时之间每一天执行一次

     

    数值递增形式(斜杠),例如3/15 其中3表示初始值,15表示递增值,表示在3,18,号执行

     

    任意值(通配符),例如 * 表示每天执行一次

     

    无特定值(问号),它与通配符的区别在于前者表示任意值,本身为当前字段设置了规则,而无特定值的含义是指本身没有为当前字段设置任何规则,而是由其他字段指定规则,与day-of-month存在交集的就是day-of-week字段。问号的意思是由另外一方指定规则。

     

           L,它有三种含义,

    1. 当只有L时,表示当前月的最后一天
    2. 当为num L时,num的范围为1-7,表示星期一到星期日,例如3L,表示最后一个星期的星期三。
    3. 当L-num时,表示当前月的最后几天,例如L-2,表示当月的最后两天。

     

           W,英文全称为WeekDay,表示工作日,即星期一到星期五。

           它表示最近的工作日,格式为num L。例如2W,表示离当月2号最近的一个工作日,总共有以下三种情形

    1. 当月2号为星期六,则会在1号星期五执行
    2. 当月2号为星期日,则会在3号星期一执行
    3. 当月2号为工作日,则会在2号的工作日执行。

          不论是哪种形式,不会跨月,例如1号为星期六,只会在3号星期一执行

      3.2.5  月

    格式基本与小时,分,秒相同,区别在于月有数值和缩写两种形式。

    格式

    num或abbr ,— * /

    允许值

    1-12

    是否必填

    示例

    单个数值/缩写形式,例如1表示在第1月执行,JAN的含义相同

    多个数值/缩写形式(逗号),例如1,3,5  表示在第1,3,5月执行

    数值/缩写范围形式(横杠),例如1-13  表示在1-3月之间执行

    数值/缩写递增形式(斜杠),例如1/5 其中1表示初始值,5表示递增值,表示在1,6, 11月执行

    任意值(通配符),例如 * 表示每月执行一次

      3.2.6   周

    格式

    num ,— * / ? L #

    允许值

    1-7

    是否必填

    示例

    单个数值/缩写形式,例如1 表示在星期一执行

     

    多个数值/缩写形式(逗号),例如1,4  表示在周一,周四执行

     

    数值/缩写范围形式(横杠),例如1-3  表示在周一,周二,周三执行

     

    数值/缩写递增形式(斜杠),例如3/2 其中3表示初始值,2表示递增值,表示在周三,周六执行

     

    任意值(通配符),例如 * 表示每天执行一次

     

    无特定值(问号),它与通配符的区别在于前者表示任意值,本身为当前字段设置了规则,而无特定值的含义是指本身没有为当前字段设置任何规则,而是由其他字段指定规则,与day-of-week存在交集的就是day-of-month字段。问号的意思是由另外一方指定规则。

     

           L,它有三种含义,与day-of-month的含义相同

    1. 当只有L时,表示当前月的最后一天
    2. 当为num L时,num的范围为1-7,表示星期一到星期日,例如3L,表示最后一个星期的星期三。
    3. 当L-num时,表示当前月的最后几天,例如L-2,表示当月的最后两天。

          注:它的周期是月,不是周

     

    #,它的格式为num1 # num2,num1的值为1-7,表示周一到周日,num2的值为当月的第几周,一般不会超过5。例如 2#3,表示当月的第三周的周二。当计算得出无实际日期时,不会出错但也无任何含义,例如5#6,当月第六周的周五无任何含义。

    3.2.7      年

    格式

    num ,— * /

    允许值

    Empty,1970-2099

    是否必填

    示例

    单个数值形式,例如2020 表示在2020年执行

    多个数值形式(逗号),例如2020,2025  表示在2020年和2025年执行

    数值范围形式(横杠),例如2020-2025  表示在2020-2025之间执行

    数值递增形式(斜杠),例如2020/10 其中2020表示初始值,10表示递增值,表示在2020,2030, 2040等年份执行

    任意值(通配符),例如 * 表示每年执行

        在使用Cron表达式时,需要注意间隔的时间单位会根据表达式推算出来,例如0/15设置在秒字段,会导致一分钟执行四次任务。

    3.3     MisFire

    当CronTrigger未被正常触发之后,有以下三种策略。

    MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY

    /**
     * Instructs the <code>{@link Scheduler}</code> that the 
     * <code>Trigger</code> will never be evaluated for a misfire situation, 
     * and that the scheduler will simply try to fire it as soon as it can, 
     * and then update the Trigger as if it had fired at the proper time. 
     * 
     * <p>NOTE: if a trigger uses this instruction, and it has missed 
     * several of its scheduled firings, then several rapid firings may occur 
     * as the trigger attempt to catch back up to where it would have been. 
     * For example, a SimpleTrigger that fires every 15 seconds which has 
     * misfired for 5 minutes will fire 20 times once it gets the chance to 
     * fire.</p>
     */
    public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;
    

      短时间内快速的执行任务。与SimpleTrigger的第一种策略相同。不适用于无限重复的任务

      MISFIRE_INSTRUCTION_DO_NOTHING

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link CronTrigger}</code> wants to have it's
     * next-fire-time updated to the next time in the schedule after the
     * current time (taking into account any associated <code>{@link Calendar}</code>,
     * but it does not want to be fired now.
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;
    

      未被触发的被忽略,之后的计算下次执行时间。

      MISFIRE_INSTRUCTION_FIRE_NOW

    /**
     * <p>
     * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
     * situation, the <code>{@link CronTrigger}</code> wants to be fired now
     * by <code>Scheduler</code>.
     * </p>
     */
    public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
    

      在now执行一次,之后计算下次的执行时间,等价于MISFIRE_INSTRUCTION_SMART_POLICY。

    4、TriggerListener

    除TriggerListener之外,TriggerBuilder, TriggerKey, TriggerDataMap与Job中的相关对象含义基本相同,不再重复。

    TriggerListener的源码如下:

    public interface TriggerListener {
        public String getName();
        public void triggerFired(Trigger trigger, JobExecutionContext context);
        public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
        public void triggerMisfired(Trigger trigger);
        public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode);
    }
    

      getName:返回Trigger的名称

      triggerFired:被触发时执行

      vetoJobExectution:对Job进行vote,返回true,否决Job,Job将不会再执行。默认返回false。

      triggerMisFired:未被正常触发时执行

      triggerComplete:触发完成时执行

    Listener的触发顺序分两种情况:

    当Job被否决了。顺序如下:

    1. 调用TriggerListener的triggerFired方法
    2. 调用TriggerListener的vetoJobExecution方法
    3. 调用JobListener的jobExecutionVetoed方法

    当Job未被否决时,顺序如下:

    1. 调用TriggerListener的triggerFired方法
    2. 调用TriggerListener的vetoJobExecution方法
    3. 调用JobListener的jobToBeExecuted方法
    4. 调用JobListener的jobWasExecuted方法
    5. 调用TriggerListener的triggerComplete方法。
  • 相关阅读:
    Jsp补充
    Jsp和Servlet关系
    ServletContext简介
    利用Session实现三天免登陆
    Cookie简介
    JSP简介
    线程基础--同步机制
    深思——工作面试
    response.setcontenttype的參数
    Codeforces 96D Volleyball spfa
  • 原文地址:https://www.cnblogs.com/rain144576/p/14749939.html
Copyright © 2020-2023  润新知