# 更多关于触发器

与作业一样,触发器非常容易使用,但确实包含多种自定义选项,在您全面使用Quartz之前,您需要了解和理解这些选项。此外,如前所述,您可以选择不同类型的触发器来满足不同的调度需求。

您将在第5课:简单触发器第6课:Cron触发器中了解两种最常见的触发器类型。

# 公共触发器属性

除了所有触发器类型都具有用于跟踪其身份的TriggerKey属性之外,还有许多其它属性是所有触发器类型所共有的。在构建触发器定义时,可以使用TriggerBuilder设置这些公共属性(下面将给出示例)。

以下是所有触发器类型的通用属性列表:

  • jobKey属性表示触发器触发时应执行的作业的标识。

  • startTime属性指示触发器的计划何时开始生效。该值是java.util.Date对象,用于定义给定日历日期的时间点。对于某些触发器类型,触发器实际上会在开始时间启动,而对于其它触发器类型,它只是标记应该开始遵循计划的时间。这意味着您可以在1月份存储一个触发器,其中包含诸如“每月的第5天”之类的计划,如果startTime属性设置为4月1日,则距离第一次触发还有几个月的时间。

  • endTime属性指示触发器的计划何时不再有效。换言之,日程安排为“每月第5天”、结束时间为7月1日的触发器将在6月5日最后一次启动。

其他属性(需要更多解释)将在以下小节中讨论。

# 优先事项

有时,当您有许多触发器(或Quartz线程池中的工作线程很少)时,Quartz可能没有足够的资源来立即触发计划同时触发的所有触发器。在这种情况下,您可能需要控制哪些触发器在可用的Quartz工作线程上优先触发。为此,可以在触发器上设置优先级属性。如果同时触发N个触发器,但当前只有Z个工作线程可用,则将首先触发具有最高优先级的第一个Z个触发器。如果您没有在触发器上设置优先级,那么它将使用默认优先级5。允许任何整数值作为优先级,无论是正值还是负值。

注意:只有当触发器具有相同的触发时间时,才会比较优先级。预定于10:59触发的触发器将总是在预定于11:00触发的触发器之前触发执行。

注意:当检测到触发器的作业需要恢复时,其恢复计划的优先级与原始触发器相同。

# 未触发指令

触发器的另一个重要特性是它的“未触发指令”。如果由于调度程序关闭或Quartz的线程池中没有用于执行作业的可用线程,导致持久性触发器“错过”其触发时间,则会发生不奏效的情况。不同的触发器类型有不同的未触发指令。默认情况下,它们使用“智能策略”指令,该指令具有基于触发器类型和配置的动态行为。当调度程序启动时,它会搜索任何不奏效的持久触发器,然后根据各自配置的未触发指令更新每个触发器。当您开始在自己的项目中使用Quartz时,您应该熟悉在给定触发器类型上定义并在JavaDoc中解释的未触发指令。有关未触发指令的更多具体信息将在针对每种触发器类型的教程中给出。

# 日历

Quartz的Calendar对象(不是java.util.Calendar对象)可以在定义触发器并存储在调度器中时与触发器关联。日历对于从触发器的触发计划中排除时间块非常有用。例如,您可以创建一个触发器,在每个工作日上午9:30启动一个工作,但随后添加一个日历,该日历排除了所有业务假日。

Calendar对象可以是实现Calendar接口的任何可序列化对象,如下所示:

Calendar接口

package org.quartz;

public interface Calendar {

  public boolean isTimeIncluded(long timeStamp);

  public long getNextIncludedTime(long timeStamp);

}

请注意,这些方法的参数是长整型的。正如你可能猜到的,它们是毫秒格式的时间戳。这意味着日历可以“屏蔽”一毫秒的时间段。最有可能的是,你会对一整天的“封锁”感兴趣。为了方便起见,Quartz包含的org.quartz.impl.HolidayCalendar类就是这样做的。

日历必须通过addCalendar(..)方法实例化并注册到调度程序。如果您使用HolidayCalendar,在实例化它之后,您应该使用它的addExcludedDate(Date Date)方法,以便用您希望从计划中排除的日期填充它。同一日历实例可以与多个触发器一起使用,例如:

Calendar例子

HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
cal.addExcludedDate( someOtherDate );

sched.addCalendar("myHolidays", cal, false);


Trigger t = newTrigger()
    .withIdentity("myTrigger")
    .forJob("myJob")
    .withSchedule(dailyAtHourAndMinute(9, 30)) //每天9:30执行作业
    .modifiedByCalendar("myHolidays") //排除假日
    .build();

//用触发器将该作业列入计划

Trigger t2 = newTrigger()
    .withIdentity("myTrigger2")
    .forJob("myJob2")
    .withSchedule(dailyAtHourAndMinute(11, 30)) //每天11:30执行作业
    .modifiedByCalendar("myHolidays") //排除假日
    .build();

//用触发器2将该作业列入计划

触发器的构造/构建细节将在接下来的几节课中给出。现在,只要知道上面的代码创建了两个触发器,每个触发器都计划每天触发。但是,将跳过在日历排除的期间内发生的任何执行。

参见实现了org.quartz.impl.calendar包的多种日历对象,可满足您的需求。


微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。