【发布时间】:2013-09-19 05:08:52
【问题描述】:
假设我有像 0 0 12 1/1 * 这样的 Cron 表达式? * 由于某些原因,服务器在 11:50 到 12:05 之间停止,并且在这种情况下,它在 12:05 之后再次启动,一旦服务器启动,我如何触发错过的预定 Cron 表达式?石英有没有解决上述问题的方法。
【问题讨论】:
标签: java quartz-scheduler
假设我有像 0 0 12 1/1 * 这样的 Cron 表达式? * 由于某些原因,服务器在 11:50 到 12:05 之间停止,并且在这种情况下,它在 12:05 之后再次启动,一旦服务器启动,我如何触发错过的预定 Cron 表达式?石英有没有解决上述问题的方法。
【问题讨论】:
标签: java quartz-scheduler
我也遇到过希望在服务器重新启动时运行最后一个计划作业的问题。
我找到的解决方案是返回触发器的一个时间间隔并计算下一次触发时间。通过遍历所有触发器,可以确定触发器在过去应该触发的最近时间。
计算每次发射的间隔时间:
Date nextFireTime = trigger.getNextFireTime();
Date subsequentFireTime = trigger.getFireTimeAfter(nextFireTime);
long interval = subsequentFireTime.getTime() - nextFireTime.getTime();
在过去的时间间隔内查找下一次触发时间:
Date previousPeriodTime = new Date(System.currentTimeMillis() - interval);
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime);
我发现如果您使用的是CronTrigger,这会阻止您在过去要求开火时间。为了解决这个问题,我修改了开始时间,所以上面的 sn-p 变为:
Date originalStartTime = trigger.getStartTime(); // save the start time
Date previousPeriodTime = new Date(originalStartTime.getTime() - interval);
trigger.setStartTime(previousPeriodTime);
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime);
trigger.setStartTime(originalStartTime); // reset the start time to be nice
遍历所有触发器并找到最近的触发器:
for (String groupName : scheduler.getTriggerGroupNames()) {
for (String triggerName : scheduler.getTriggerNames(groupName)) {
Trigger trigger = scheduler.getTrigger(triggerName, groupName);
// code as detailed above...
interval = ...
previousFireTime = ...
}
}
此代码可以重构为辅助方法或类。我实际上在一个子类委托触发器中使用了上述算法,然后我将其放入按先前触发时间排序的集合中。
【讨论】:
请参阅 Quartz 文档 tutorials 或 this 伟大的文章“Misfire Instructions”,这是从 Quartz 触发器中用于恢复错过的作业执行的策略。
如果您想容忍服务器关闭/崩溃,您需要将 Quartz 配置为使用持久的 Job Store 来点赞JDBCJobStore 以“记住”崩溃前的最后一次作业执行。
更新:请参阅 this answer,了解如何创建可恢复的作业。
【讨论】: