如果同一作业的另一个实例已在执行(如果正在运行相同的“JobDetail”),我想跳过作业执行。我知道注释“@DisallowConcurrentExecution”避免同时执行同一个作业。但缺点是,当作业(执行的作业时间较长,然后触发周期性)完成后,作业将立即重新执行。我希望在下一个计划开火时间内执行该工作。
工作实施
public class LongJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
System.out.println("Executed: " + LocalDateTime.now().toString());
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
调度
JobDetail job2 = JobBuilder.newJob(LongJob.class)
.withIdentity("job2")
.build();
Trigger trigger2 = TriggerBuilder.newTrigger()
.forJob(job2)
.startNow()
.withIdentity("job2-trigger")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/3 * * ? * *")
.withMisfireHandlingInstructionIgnoreMisfires())
.build();
scheduler.scheduleJob(job2, trigger2);
预期输出
Executed: 2016-02-18T10:11:15
Executed: 2016-02-18T10:11:21
Executed: 2016-02-18T10:11:27
Executed: 2016-02-18T10:11:33
使用@DisallowConcurrentExecution输出
Executed: 2016-02-18T10:11:15
Executed: 2016-02-18T10:11:20
Executed: 2016-02-18T10:11:25
Executed: 2016-02-18T10:11:30
我使用Trigger Listeners制作了一个解决方案,但我想知道是否有一个更简单的解决方案。在这种方法中,我会为触发相同作业的每组触发器使用一个监听器实例(我可以使用不同的触发器来解决我的“更大”问题,避免对不同的作业使用相同的触发器。)
class CustomTriggerListener extends TriggerListenerSupport {
private JobExecutionContext lastJobExecutionContext;
@Override
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
boolean vetoExecution = false;
if (lastJobExecutionContext == null) {
lastJobExecutionContext = context;
} else {
boolean lastJobIsDone = lastJobExecutionContext.getJobRunTime() >= 0;
if (lastJobIsDone) {
lastJobExecutionContext = context;
} else {
vetoExecution = true;
}
}
return vetoExecution;
}
@Override
public String getName() {
return "CustomTriggerListener";
}
}