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)我使用的自定义数据存储不支持触发子类。