前面出了一个20000+元的 Bug,现在来认真的看看 Spring Schedule 是如何处理定时任务的。
Spring Schedule 配置时间的三种方式
- fixRate: 间隔时间,会根据首次执行时间预先安排固定的时间,错过立即执行
- fixDelay: 间隔时间,上次结束时间后多少间隔后执行
- cron: 指定具体时间,错过立即执行
fixRate 运行方式
fixRate 是会根据开始时间预先安排一系列的固定时间点,如果错过了安排的时间点,则立即执行,否则等待下一个执行时间点,如下图 fixRate=5000,每5秒执行一次,第二次执行超过了预先安排的点,导致第三次错过,则第三次立即执行,二第四次则在正常安排的时间点执行,值得注意的是第三次与第四次相隔仅一秒。
fixDelay 运行方式
fixDelay 就相对简单一些,上次执行完开始计时,到时间就执行。会有一种特殊情况,如果间隔时间到了,没有可用于执行的线程,那么下次获取到线程后立即执行。如下图 fixDelay=5000,每5秒执行一次:
cron 运行方式
cron 可以指定具体的时间,和 fixRate 有些类似,错过立即执行。我前面的bug就是因为这个原因引起的,一台实例开始执行并加了锁,按理说其他实例相同时间则获取锁失败跳过执行,但另一个实例由于定时任务未能获取到执行线程,延后了,获取到线程后立即执行,导致这个时间不正常,而且前面的锁的时间不够长,导致重复执行。
TODO
一些可以扩展了解的地方 - [ ] schedule 自定义线程池 - [ ] 多实例环境下如何保证唯一 - [ ] 一些定时任务可选方案