Quartz如何监控触发器执行完成?TriggerListener获取状态异常求助
Quartz触发器执行完成状态的判断方法
你遇到的问题是因为在triggerComplete回调执行时,Quartz调度器尚未完成触发器状态的更新,所以直接调用getTriggerState会得到旧的Normal状态。以下是几种可靠的判断方式:
1. 利用CompletedExecutionInstruction参数判断
triggerComplete方法的第三个参数triggerInstructionCode直接指示了Quartz对当前触发器的后续处理策略,通过它可以准确判断触发器是否执行完毕且不再触发:
@Override public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) { // 判断触发器是否会被标记为完成或删除 boolean isCompleted = triggerInstructionCode == Trigger.CompletedExecutionInstruction.DELETE || triggerInstructionCode == Trigger.CompletedExecutionInstruction.SET_COMPLETE; if (isCompleted) { log.info("触发器 {} 已执行完毕,后续不再触发", trigger.getKey()); } else { log.info("触发器 {} 执行完成,但会继续触发", trigger.getKey()); } }
DELETE:执行完成后触发器会被从调度器中删除(比如一次性触发器)SET_COMPLETE:触发器会被标记为COMPLETE状态,不再触发
2. 结合触发器的原始配置判断
如果是一次性触发器(比如SimpleTrigger的repeatCount=0,或者CronTrigger只执行一次),可以结合触发器本身的配置来判断:
@Override public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) { boolean isOneTimeTrigger = false; // 判断是否为一次性SimpleTrigger if (trigger instanceof SimpleTrigger) { SimpleTrigger simpleTrigger = (SimpleTrigger) trigger; isOneTimeTrigger = simpleTrigger.getRepeatCount() == 0; } // 判断是否为一次性CronTrigger(比如Cron表达式只匹配一次) else if (trigger instanceof CronTrigger) { CronTrigger cronTrigger = (CronTrigger) trigger; CronExpression cronExpr = cronTrigger.getCronExpression(); // 检查下一次触发时间是否为null(表示没有下一次触发) isOneTimeTrigger = cronExpr.getNextValidTimeAfter(new Date()) == null; } if (isOneTimeTrigger && triggerInstructionCode != Trigger.CompletedExecutionInstruction.RE_EXECUTE_JOB) { log.info("一次性触发器 {} 已执行完毕", trigger.getKey()); } }
3. 延迟获取触发器状态(不推荐)
如果一定要通过getTriggerState判断,可以短暂延迟后再获取,但这种方式依赖调度器的状态更新速度,可靠性较低:
@Override public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) { new Thread(() -> { try { // 延迟100ms等待状态更新 Thread.sleep(100); Trigger.TriggerState state = context.getScheduler().getTriggerState(trigger.getKey()); if (state == Trigger.TriggerState.COMPLETE || state == Trigger.TriggerState.NONE) { log.info("触发器 {} 已执行完毕,状态:{}", trigger.getKey(), state); } } catch (SchedulerException | InterruptedException e) { throw new RuntimeException(e); } }).start(); }
内容的提问来源于stack exchange,提问作者Mr.tang
相关产品推荐
相关产品推荐

