Quartz Java恢复工作多次使用它
对于我的应用程序,我创建作业并使用CronTriggers安排它们。 每个作业只有一个触发器,作业名称和触发器名称都相同。 没有工作共享触发器。
现在当我创建像这样的“0/1 * * * *?”的cron触发器时 它指示作业每秒执行一次,它运行得很好。
当我第一次暂停工作时,问题就出现了:
scheduler.pauseJob(jobName, jobGroup);
然后让我们说50秒后恢复工作:
scheduler.resumeJob(jobName, jobGroup);
我所看到的是,在这50秒内,作业没有按要求执行。 但是当我恢复工作的那一刻,我同时看到了50份执行工作!
我认为这是由于失火指令的默认设置,但即使在创建时将触发器的失火指示设置为:
trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
同样的事情发生了。 任何人都可以建议一种解决方法吗?
CronTrigger
通过记住nextFireTime
。 创建触发器后,初始化nextFireTime
。 每次触发作业时, nextFireTime
都会更新。 暂停时, nextFireTime
保持“旧”状态,因此未触发作业。 因此,在您恢复作业后,触发器将返回每个旧的触发时间。
问题是,触发器不知道它被暂停了。 为了解决这个问题,有这种失火处理。 恢复作业后,将调用触发器的updateAfterMisfire()
方法来纠正nextFireTime
。 但是,如果nextFireTime
和now之间的差异小于nextFireTime
,则不会 。 然后永远不会调用该方法。 此阈值的默认值为60,000。 因此,如果您的暂停时间超过60秒,一切都会好的。
既然你有问题,我认为不是。 ;)要解决此问题,您可以修改阈值或使用CronTrigger
周围的简单包装器:
public class PauseAwareCronTrigger extends CronTrigger { // constructors you need go here @Override public Date getNextFireTime() { Date nextFireTime = super.getNextFireTime(); if (nextFireTime.getTime() < System.currentTimeMillis()) { // next fire time after now nextFireTime = super.getFireTimeAfter(null); super.setNextFireTime(nextFireTime); } return nextFireTime; } }
如果暂停作业,触发器将继续触发,但执行将排队,直到作业恢复。 这不是失误的触发器,因此设置将不起作用。
我认为,您想要以编程方式禁用或删除cron触发器,而不是暂停作业。 如果要恢复,请重新添加触发器。
至少1.6.5(最早的石英版本在我的指尖),调度程序有一个pauseTrigger方法,它将名称/组作为参数。 这意味着您不必拥有您使用的每种触发类型的子类,也不必执行时髦的删除/插入技巧。
这两个对我来说都很重要因为1)我们的数据库有严格的no-deletes策略; 2)我使用的自定义数据存储不支持触发子类。