Quartz的misfire处理策略设置不当导致Job在应用启动时立即执行。
问题分析
在您的代码中:
trigger = newTrigger()
.withIdentity("SingleJobStockIgniteToRedis", "task_SingleJobStockIgniteToRedis")
.withSchedule(cronSchedule(cron).withMisfireHandlingInstructionDoNothing())
.build();
关键问题:
-
withMisfireHandlingInstructionDoNothing()只处理触发时间已经过去的情况,不处理应用启动时的行为 -
Quartz默认在Scheduler启动时会立即执行所有错过的Job(missed trigger)
-
您的cron表达式
"17 0 15 ? * 2-6"表示:每周二到周六的15:00:17执行 -
如果启动时间在这个时间点之后,Quartz会认为该Job应该被触发但错过了
解决方案
方案1:使用 startAt() 设置未来时间(推荐)
trigger = newTrigger()
.withIdentity("SingleJobStockIgniteToRedis", "task_SingleJobStockIgniteToRedis")
.startAt(DateBuilder.futureDate(10, DateBuilder.IntervalUnit.SECOND)) // 10秒后开始
.withSchedule(cronSchedule(cron)
.withMisfireHandlingInstructionDoNothing())
.build();
方案2:使用 startNow(false) 明确不立即启动
trigger = newTrigger()
.withIdentity("SingleJobStockIgniteToRedis", "task_SingleJobStockIgniteToRedis")
.startNow(false) // 明确设置不立即启动
.withSchedule(cronSchedule(cron)
.withMisfireHandlingInstructionDoNothing())
.build();
方案3:设置初始延迟时间
trigger = newTrigger()
.withIdentity("SingleJobStockIgniteToRedis", "task_SingleJobStockIgniteToRedis")
.withSchedule(cronSchedule(cron)
.withMisfireHandlingInstructionDoNothing()
.withMisfireHandlingInstructionIgnoreMisfires()) // 或者忽略错过的
.build();
方案4:修改misfire策略(更彻底)
// 使用 MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 忽略所有错过的
trigger = newTrigger()
.withIdentity("SingleJobStockIgniteToRedis", "task_SingleJobStockIgniteToRedis")
.withSchedule(cronSchedule(cron)
.withMisfireHandlingInstructionIgnoreMisfires())
.build();
浙公网安备 33010602011771号