上一篇中讲了在项目中简单使用Quartz,其中有一点是看博客时注意到的,虽然项目中实际不太可能出现misfire的情况,但还是初步了解了下。
Quartz中有一种job接口,是StatefulJob,有状态任务,简单来说,这种job使用在不能并发执行的场景下。比如定义了某个任务,每分钟执行一次,对一些数据进行增删操作,正常执行时,每分钟执行的job互不影响,但某个时刻出现了意外,某个任务执行了三分钟。那么,在这个任务持续执行的过程中,我们是不希望并发执行另外两次“例行”任务的,这就需要使用有状态任务,而没有执行的两次任务就是misfired job。
对于判定为misfired job,其实有很多条件,目前了解到的有:
0. 到执行时间时,上一个任务还未完成;
1. 过期时间已超过设置的misfireThreshold;
2.1. 线程池中已没有空闲线程
2.2. 线程池中虽有空闲线程,但有优先级更高的任务
产生misfire后,会根据设置的misfire策略进行任务的处理。
对CronTrigger来说,有三种misfire策略:
MISFIRE_INSTRUCTION_SMART_POLICY = 0
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1
MISFIRE_INSTRUCTION_DO_NOTHING = 2
MISFIRE_INSTRUCTION_SMART_POLICY是默认的策略,从字面意思去理解,应该是会自动选择具体的trigger实现类中的具体策略吧,没有详细的了解。
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW是立即触发一次,触发后恢复正常的频率。
MISFIRE_INSTRUCTION_DO_NOTHING是什么都不做,继续等下一次预定时间再触发。
对SimpleTrigger有更多种策略:
因为用Cron就基本满足各种各样的触发配置,所以对Simple基本没做过多的了解
以我做的项目来说,使用DO_NOTHING就可以满足情况了,就是说,即使产生了misfired job,那在上一个job全部执行完后,什么都不要做,等下一个触发时间到了的时候,再照常执行就可以了。所以在配置中使用了这种misfire策略,就是在CronTriggerBean中配置了:<property name="misfireInstruction" value="2" />
参考资料:
https://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/
http://www.cnblogs.com/pzy4447/p/5201674.html
http://blog.sina.com.cn/s/blog_56d8ea900101eu45.html
https://dzone.com/articles/quartz-scheduler-misfire