私のアプリケーションでは、ジョブを作成し、CronTriggers を使用してスケジュールします。各ジョブにはトリガーが 1 つだけあり、ジョブ名とトリガー名は同じです。トリガーを共有するジョブはありません。
では、このようなcronトリガーを作成すると「0/1 * * * * ?」これはジョブを毎秒実行するように指示するもので、問題なく動作します。
問題は、最初に次の呼び出しでジョブを一時停止したときに発生します。
scheduler.pauseJob(jobName, jobGroup);
そして、たとえば 50 秒後にジョブを再開します。
scheduler.resumeJob(jobName, jobGroup);
私が確認したのは、この 50 秒間、ジョブが要求どおりに実行されなかったということです。しかし、ジョブを再開した瞬間、ジョブが同時に 50 回実行されているのがわかります。
これはミスファイア命令のデフォルト設定によるものだと思っていましたが、作成時にトリガーのミスファイア命令を次のように設定した後でも、
trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
同じことが起こります。これを修正する方法を誰か提案できますか?
ベストアンサー1
CronTrigger
は を記憶することで機能します。nextFireTime
トリガーを作成した後、 はnextFireTime
初期化されます。ジョブがトリガーされるたびにnextFireTime
が更新されます。一時停止時にジョブがトリガーされないため、nextFireTime
ジョブは「古い」ままになります。そのため、ジョブを再開すると、トリガーは古いトリガー時間ごとに返します。
問題は、トリガーが一時停止中であることを認識していないことです。これを克服するために、このミスファイア処理があります。ジョブを再開した後、トリガーのupdateAfterMisfire()
メソッドが呼び出され、 を修正しますnextFireTime
。ただし、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;
}
}