Trigger详解
- 通用的Trigger属性
所有类型的触发器都有TriggerKey属性去跟踪触发器标识,还有许多其他的属性,对所有触发器类型都适用。这些通用属性在创建触发器定义时通过TriggerBuilder类来设定的(下面会有例子)。
下面的属性列表对所有类型的触发器都通用:
- jobKey:表示job实例的标识,触发器点火时,该job实例会被执行。
- startTime:表示触发器的时间表首次被触发的时间。它的值是 java.util.Date 对象,定义了给定日器的时刻。对于一些类型的触发器,会在启动时间触发,另一些触发器则仅仅是标示了调度器将要被触发的时间。这意味着你可以在调度器中存储一个触发器,例如每月的5号,如果现在是一月份,而startTime参数又设置为4月1日,那这样需要几个月后触发器才会第一次被触发。
- endTime:指定触发器的调度计划不再被触发的时间。换言之,调度器中的触发器定义为“每月的5号”,而且endTime设置为7月1日,那么6月5日将会是最后一次触发的日期。
- 优先级
有些时候,当你有许多触发器(或Quartz线程池中只有少数几个工作线程),Quartz可能没有足够的资源去触发所有的在同一时间段内排定好的触发器。既然这样,你可能期望控制哪个触发器能第一个获得Quartz空闲工作线程的调用。为了达到这个目的,你可以设定触发器的Priority属性。如果N个触发器在同一时间内被触发,但只有Z工作线程当前空闲可用,那么拥有最高优先级的Z触发器将会第一个被触发。如果你没有设置触发器的优先级,它将会使用默认的优先级,优先级值为5。任何Integer类型的值都可以作为优先级,正数负数都可以。
- 触发失败指令
触发器另外一个重要的属性就是“misfire instruction”。触发失败的情况是由于调度器被关闭导致存储的触发器错过了触发的时间,或是由于Quartz线程池内没有空闲的线程去执行作业任务。不同类型的触发器有不同的触发失败处理机制。默认情况下使用“智能策略”指令——基于触发器类型和配置的动态机制。当调度器启动时,它会查询所有存储的、触发失败的触发器,然后根据各自配置的触发失败指令更新触发器。当你开始在你的项目中使用Quartz时,你应该让自己熟悉在给定触发器类型上定义的触发失败指令和API上的文档解释。更多关于触发失败指令的详细信息将会在教程里每个触发器类型课程中作详细介绍。
SimpleTrigger
如果你需要在一个指定时间段内执行一次作业任务或是在指定的时间间隔内多次执行作业任务,SimpleTrigger应该能满足你的调度需求。例如,你希望触发器在2015年1月13日上午11:23:54准时触发,或是希望在那个时间点触发,然后再重复触发5次,每隔10秒一次。有了这样的描述,你就不会对SimpleTrigger包含的参数感到奇怪:开始执行时间,结束执行时间,重复次数和重复执行间隔时间。所有的参数都是你期望的那样,只是关于结束执行时间参数有两条特别的提示。
- 重复次数可以为0,正整数或是SimpleTrigger.REPEAT_INDEFINITELY常量值。
- 重复执行间隔必须为0或长整数(long类型),它表示毫秒数的值。注意如果重复执行间隔时间为0会导致数量为“重复次数”的触发器并发执行(或是在调度器控制下接近并发执行)。
endTime参数(如果被指定)会覆盖重复次数参数。当你希望创建一个触发器,每隔10秒被触发一次,直到给定的截止时间,而不是必须完成在给定的开始和结束时间段内的触发次数,使用endTime参数会非常方便,你可以仅仅指定一个end-time参数,并且将重复次数设置为REPEAT_INDEFINITELY(你甚至可以将重复次数指定为非常大的值,确保比结束执行时间到达前实际要执行的次数大就行)。
下面是使用简易调度器定义触发器的几个案例,请通读一遍,每个例子都至少演示了一个新的、不同的知识点:
- 创建触发器时,指定时刻,不重复执行:
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(myStartTime) // some Date
.forJob("job1", "group1") // identify job with name, group strings
.build();
- 创建触发器时,指定时刻,然后每隔10秒触发一次,共重复触发10次:
Trigger trigger = newTrigger()
.withIdentity("trigger3", "group1")
.startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
.forJob(myJob) // identify job with handle to its JobDetail itself
.build();
- 创建触发器,5分钟后执行一次:
Trigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
.forJob(myJobKey) // identify job with its JobKey
.build();
- 创建触发器时立即触发,然后每隔5分钟触发一次,直到22:00:
Trigger trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0))
.build();
- 创建触发器时,在下一个整点小时触发,然后每隔2小时触发一次,永不停歇:
Trigger trigger = newTrigger()
.withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
.startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
// note that in this example, 'forJob(..)' is not called
// - which is valid if the trigger is passed to the scheduler along with the job
.build();
CronTrigger
当你需要一个基于日历概念的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间时,CronTrigger比SimpleTrigger更常用。
使用CronTrigger,你可以这样指定触发时间表,例如“每周五的中午”,或是“每周末的上午9:30”,甚至是“一月份每周一、三、五上午9:00到10:00之间每5分钟”。
虽然如此,跟SimpleTrigger一样,CronTrigger也需要指定startTime让调度器生效,指定endTime让调度器终止。
- Cron表达式
Cron表达式用于配置CronTrigger实例。Cron表达式实际上是由7个子表达式组成的字符串,描述了schedule的详细信息。这些子表达式用空格隔开,分别代表:
秒
分
时
月份中的天数
月
星期中的天数
年(可选字段)
下面展示一些基于cron表达式构建的示例
- 构建一个trigger,每天的从上午8点到下午5点,每两分钟触发一次:
Trigger trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1")
.build();
- 构建一个trigger,每天上午10:42触发:
Tigger trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(dailyAtHourAndMinute(10, 42))
.forJob(myJobKey)
.build();
- 构建一个trigger,在周三上午10:42(指定时区TimeZone,而不是系统默认时区)触发:
Trigger trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 ? * WED"))
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.forJob(myJobKey)
.build();
评论区