Quartz Java 恢复作业会多次执行它

对于我的应用程序,我创建工作并使用CronTriggers安排它们。每个作业只有一个触发器,并且作业名称和触发器名称相同。没有作业共享触发器。

现在,当我创建一个像“0/1 * * ?”这样的cron触发器时,它指示作业每秒执行一次,它工作得很好。

当我第一次通过调用来暂停作业时,问题就出现了:

scheduler.pauseJob(jobName, jobGroup);

然后在 50 秒后恢复工作::

scheduler.resumeJob(jobName, jobGroup);

我看到的是,在这50秒内,作业没有按照要求执行。但是当我恢复工作时,我看到同时执行了50个工作!!!

我认为这是由于失火指令的默认设置,但即使在创建时将触发器的失火指令设置为以下情况:

trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);

同样的事情也发生了。任何人都可以建议一种方法来解决这个问题吗?


答案 1

通过记住.创建触发器后,将初始化。每次触发作业时都会更新。由于暂停时作业未触发,因此保持“旧”。因此,在恢复作业后,触发器将返回每个旧的触发时间。CronTriggernextFireTimenextFireTimenextFireTimenextFireTime

问题是,触发器不知道它正在暂停。为了克服这一点,有这种错误的处理。恢复作业后,将调用触发器的方法,以更正 .但是,如果和现在之间的差异小于失火阈值,则不会。然后从不调用该方法。此阈值的默认值为 60,000。因此,如果你的暂停期超过60秒,一切都会好起来的。updateAfterMisfire()nextFireTimenextFireTime

既然你有问题,我就认为不是。;)要解决此问题,您可以修改阈值或使用简单的包装器: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;
    }
}

答案 2

如果暂停作业,触发器将继续触发,但执行将排队,直到作业恢复。这不是误射触发器,因此该设置将不起作用。

我认为,您要做的是以编程方式禁用或删除 cron 触发器,而不是暂停作业。如果要恢复,请重新添加触发器。


推荐