定时任务调度框架Quartz--Misfire处理规则
文章目录
纸上得来终觉浅,绝知此事要躬行。亲测得出的结论。
SimpleTrigger
结论
策略 | 编码 | 结论 |
---|---|---|
withMisfireHandlingInstructionIgnoreMisfires | -1 | IgnoreMisfires把所有错过的定时任务一次性执行。即使定时任务执行的时间已经结束,它也会把所有应该执行的任务一次性全部执行完。这个不是忽略已经错失的触发的意思,而是说忽略MisFire策略。它会在资源合适的时候,重新触发所有的MisFire任务,并且不会影响现有的调度时间 |
withMisfireHandlingInstructionFireNow | 1 | FireNow开发者希望只执行一次的定时任务使用FireNow这种策略。从执行效果上来看,如果该定时任务本该执行却因为种种原因没有执行,那么该策略在程序启动的时候会追回执行一次。即使结束时间已经过了,也会执行一次,坚持不懈的精神值得表扬 |
withMisfireHandlingInstructionNowWithExistingCount | 2 | NowWithExistingCount表示如果有任何一次错过的执行,那么在程序启动的时候会执行一次,然后继续按照正常的频率执行接下来的调度任务,直到程序结束。如果结束时间已经过了,则不会再执行 |
withMisfireHandlingInstructionNowWithRemainingCount | 3 | NowWithRemainingCount表示忽略已经错过的任务,以当前时间为触发起点立即触发执行,并按照正常的频率执行,直到任务时间结束。如果当前时间已经超过结束时间,则不会再执行 |
withMisfireHandlingInstructionNextWithRemainingCount | 4 | NextWithRemainingCount表示忽略已经错过的调度,按照正常频率执行下次定时任务,直到任务结束。如果已经超过结束时间,那么就不了了之,不再执行。综上,NextWithRemainingCount不触发立即执行——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数 |
withMisfireHandlingInstructionNextWithExistingCount | 5 | NextWithRemainingCount几乎与withMisfireHandlingInstructionNextWithRemainingCount相同 |
还有一个编码是0的,我就偷个懒了。从网上找了资料
withMisfireHandlingInstructionIgnoreMisfires
public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;
IgnoreMisfires策略会把所有错过的定时任务一次性执行。即使定时任务执行的时间已经结束,它也会把所有应该执行的任务一次性全部执行完。这个不是忽略已经错失的触发的意思,而是说忽略MisFire策略。它会在资源合适的时候,重新触发所有的MisFire任务,并且不会影响现有的调度时间。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger5 = newTrigger().withIdentity("trigger5", "group1")
.startAt(DateBuilder.todayAt(16, 0, 0))
.withSchedule(
simpleSchedule().withIntervalInMinutes(60)
.repeatForever()
//把所有应该执行而没有执行的定时任务一次性全部执行
.withMisfireHandlingInstructionIgnoreMisfires()
).forJob("job1", "group1")
.endAt(DateBuilder.todayAt(18, 0, 0))
.build();
scheduler.scheduleJob(job, trigger5);
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是从16点开始执行定时任务,每个小时执行一次,直到18点。因为启动程序时间在17点50分,所以本应该执行16点一次任务,17点一次任务。
程序的运行结果表明,在启动之时立刻追加执行本该执行的2次打印任务。
withMisfireHandlingInstructionFireNow
public static final int MISFIRE_INSTRUCTION_FIRE_NOW = 1;
FireNow这种策略从作者的注释描述来看,开发者希望只执行一次的定时任务使用FireNow这种策略。从执行效果上来看,如果该定时任务本该执行却因为种种原因没有执行,那么该策略在程序启动的时候会追回执行一次。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.usingJobData("格言2", "沉默是金2")
.startAt(DateBuilder.todayAt(19, 20, 20))
.withSchedule(
simpleSchedule().
//立即执行错过的定时任务调度。这通常只适用于只执行一次的任务。
withMisfireHandlingInstructionFireNow())
.forJob(job)
.build();
scheduler.scheduleJob(job, trigger);
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的19点20分打印程序,但是程序启动却是在19点21分,所以立即根据FireNow 策略,执行19点20分错过的定时任务一次。
程序的运行结果表明,在程序启动之时立即执行在19点20分错过的定时任务。
withMisfireHandlingInstructionNowWithExistingCount
public static final int
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2;
NowWithExisingCount表示如果有任何一次错过的执行,那么在程序启动的时候会执行一次,然后继续按照正常的频率执行接下来的调度任务,直到程序结束。如果结束时间已经过了,则不会再执行。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger5 = newTrigger().withIdentity("trigger5", "group1")
.startAt(DateBuilder.todayAt(19, 45, 0))
.withSchedule(
simpleSchedule().
withIntervalInSeconds(10).withRepeatCount(10)
.withMisfireHandlingInstructionNowWithExistingCount()
).forJob("job1", "group1")
.endAt(DateBuilder.todayAt(19, 48, 0))
.build();
scheduler.scheduleJob(job, trigger5 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的19点45分到48分执行,每10秒打印一次。但是程序启动却是在19点46分,所以说明有任务错过了,因此程序在启动的时候会执行一次,然后按照正常的频率每10秒执行一次。
withMisfireHandlingInstructionNowWithRemainingCount
public static final int
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3;
NowWithRemainingCount表示忽略已经错过的任务,以当前时间为触发起点立即触发执行,并按照正常的频率执行,直到任务时间结束。如果当前时间已经超过结束时间,则不会再执行。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger5 = newTrigger().withIdentity("trigger5", "group1")
.startAt(DateBuilder.todayAt(9, 30, 0))
.withSchedule(
simpleSchedule()
.withIntervalInSeconds(10)
//repeat forever
.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY)
//忽略已经错过的任务,以当前时间为开始执行时间,按照频率正常执行
.withMisfireHandlingInstructionNowWithRemainingCount()
).forJob("job1", "group1")
.endAt(DateBuilder.todayAt(9, 40, 0))
.build();
scheduler.scheduleJob(job, trigger5 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的9点30分到40分执行,每10秒打印一次。但是程序启动却是在9点35分,所以说明有任务错过了。
NowWithRemainingCount表示忽略已经错过的任务,以当前时间为触发起点立即触发执行,并按照正常的频率执行,直到任务时间结束。
withMisfireHandlingInstructionNextWithRemainingCount
public static final int
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4;
NextWithRemainingCount表示忽略已经错过的调度,按照正常频率执行下次定时任务,直到任务结束。如果已经超过结束时间,那么就不了了之,不再执行。综上,NextWithRemainingCount不触发立即执行——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger5 = newTrigger().withIdentity("trigger5", "group1")
.startAt(DateBuilder.todayAt(9, 50, 0))
.withSchedule(
simpleSchedule()
.withIntervalInSeconds(10)
//repeat forever
.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY)
//不触发立即执行——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
.withMisfireHandlingInstructionNextWithRemainingCount()
).forJob("job1", "group1")
.endAt(DateBuilder.todayAt(9, 55, 0))
.build();
scheduler.scheduleJob(job, trigger5 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的9点50分到55分执行,每10秒打印一次。但是程序启动却是在9点52分,所以说明有任务错过了。
NextWithRemainingCount会按照执行正常频率的下次调度,所以从实际执行效果上看,执行的也都是分钟整点,印证了NextWithRemainingCount会等待下次触发频率周期时刻。
withMisfireHandlingInstructionNextWithExistingCount
public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5;
几乎与上面的NextWithRemainingCount相同。
CronTrigger
结论
策略 | 编码 | 结论 |
---|---|---|
withMisfireHandlingInstructionIgnoreMisfires | -1 | IgnoreMisfires把所有错过的定时任务一次性执行。即使定时任务执行的时间已经结束,它也会把所有应该执行的任务一次性全部执行完。这个不是忽略已经错失的触发的意思,而是说忽略MisFire策略。它会在资源合适的时候,重新触发所有的MisFire任务,并且不会影响现有的调度时间 |
withMisfireHandlingInstructionFireAndProceed | 1 | MISFIRE_INSTRUCTION_FIRE_ONCE_NOW。如果有错过的任务,在启动的时候执行一次任务,然后按照正常的调度继续执行。如果超过结束时间且有错过的任务,在启动的时候执行一次任务,然后就不再执行。 |
withMisfireHandlingInstructionDoNothing | 2 | MISFIRE_INSTRUCTION_DO_NOTHING。忽略所有错过的任务,按照正常的调度执行了。如果当前时间超过了结束时间,不做任何追加执行 |
withMisfireHandlingInstructionIgnoreMisfires
public static final int
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY= -1;
追加执行所有错过的定时任务。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger2 = newTrigger().withIdentity("trigger2", "group1")
.usingJobData("格言3", "奥特曼猪猪侠闪电小子葫芦娃")
.startAt(DateBuilder.todayAt(19,0,0))
.withSchedule(cronSchedule("0 0/10 19 * * ?").
withMisfireHandlingInstructionIgnoreMisfires())
.forJob("job1", "group1").build();
scheduler.scheduleJob(job, trigger2 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的19点00分开始,每10分钟打印一次。但是程序启动却是在19点29分,共错过3次打印,分别是19:00,19:10,19:20。
IgnoreMisfires执行所有错过的任务。如果程序说结束时间到19:29分,那么即使现在超过了19:29分,那么也是追加执行3次,亲测。
withMisfireHandlingInstructionFireAndProceed
CronTrigger.java类中
public static final int
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
如果有错过的任务,在启动的时候执行一次任务,然后按照正常的调度继续执行。如果超过结束时间且有错过的任务,在启动的时候执行一次任务,然后就不再执行。
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger2 = newTrigger().withIdentity("trigger2", "group1")
.usingJobData("格言3", "奥特曼猪猪侠闪电小子葫芦娃")
.startAt(DateBuilder.todayAt(19,0,0))
//.endAt(DateBuilder.todayAt(19,29,0))
.withSchedule(cronSchedule("0 0/1 19 * * ?").
witMisfireHandlingInstructionFireAndProceed())
.forJob("job1", "group1").build();
scheduler.scheduleJob(job, trigger2 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的19点00分开始,每1分钟打印一次。但是程序启动却是在19点41分,共错过很多次打印。
FireAndProceed或者说FIRE_ONCE_NOW在启动的时候只追加执行了一次,然后就按照正常的调度执行了。如果当前时间超过了结束时间,也会追加执行一次,然后就不再执行任何任务。
withMisfireHandlingInstructionDoNothing
CronTrigger.java类中
public static final int
MISFIRE_INSTRUCTION_DO_NOTHING= 2;
忽略所有错过的任务,在下次调度时正常执行。即对错过的任务不做任何处理
public static void main(String[] args) {
try {
//define the job and bind it to our HelloJob class
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
usingJobData("格言", "市场最小阻力路线初现的关键时刻").
build();
Trigger trigger2 = newTrigger().withIdentity("trigger2", "group1")
.usingJobData("格言3", "奥特曼猪猪侠闪电小子葫芦娃")
.startAt(DateBuilder.todayAt(19,0,0))
.withSchedule(cronSchedule("0 0/1 19 * * ?").
withMisfireHandlingInstructionDoNothing())
.forJob("job1", "group1").build();
scheduler.scheduleJob(job, trigger2 );
//在调用shutdown()之前,你需要给job的触发和执行预留一些时间,比如,你可以调用
Thread.sleep(1000000000);
scheduler.shutdown();
} catch (Exception e) {
LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
}
}
public static class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
LOGGER.error("现在是:{},JobInstanceId:{}",
DateTransformTools.dateToDateStr(new Date()), this.hashCode());
}
}
上述程序的目的是在今天的19点00分开始,每1分钟打印一次。但是程序启动却是在19点47分20秒,共错过很多次打印。
DoNothing会忽略所有错过的任务,按照正常的调度执行了。如果当前时间超过了结束时间,不做任何追加执行。