问题:将项目中的定时任务由Timer改为Quartz
Quartz是一个java开源作业调度框架。
一、核心概念:
1.Job:表示一个工作,要执行的具体内容。只有一个接口,如下:
void execute(JobExecutionContext context)
2.JobDetail:一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容,另外JobDetail还包含了Job调度的方案和策略。
3.Trigger:代表一个调度参数的配置,调度的时间。
4.Scheduler:代表一个调度容器,可以注册多个JobDetail和Trigger。当它们组合起来就可以被容器调度了。
二、Quartz API:
- Scheduler:与调度程序交互的主要API。一个Scheduler生命周期从SchedulerFactory创建开始到shutdown结束;在生存周期内,可以增加、删除和查看Job和Trigger,以及执行其他与调度相关的操作。但是只有Scheduler在调用start方法后才会真正的触发任务调度。
- Job:想要调度的任务需要实现的接口。
- JobDetail:用于定义作业的实例。
- Trigger:定义执行给定作业的计划。
- JobBuilder:用于定义/构建JobDetail的实例。
- TriggerBuilder:用于定义/构建触发器的实例
三、Job的状态与并发
- @DisallowConcurrentExecution:注解加到Job类上,不要并发的执行同一个Job类定义的多个实例。该限制作用在JobDetail而不是Job。
- @PersistJobDataAfterExecution:告诉Quartz在成功执行了Job类的execute方法后,更新JobDetail中的JobDataMap的数据。
建议使用@PersistJobDataAfterExecution时同时使用@DisallowConcurrentExecution注解,因为当同一个job的两个实例被并发执行时,由于竞争,JobDataMap中存储的数据很可能是不确定的。
四、Trigger
- Simple Trigger:可以再具体时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。
TriggerBuilder一下接口
- withIdentity("trigger3", "group1"):定义触发器名称和组。
- startNow():立刻执行
- startAt(myTimeToStartFiring):定义触发器开始时间,如果早于当前时间或没有定义则默认为当前时间。
- withSchedule(simpleSchedule()):触发间隔和触发次数。
withIntervalInSeconds(10):触发间隔。
withRepeatCount(10):触发次数。
repeatForever():一直重复。
- forJob("myJob","group1"):绑定任务。
- build():构建完成补全参数。
坑:原需求是延迟1周执行,在测试接口的时候,simpletrigger设置的是当前时间半分钟后,连续调用多次接口发现只执行了一个作业,查看数据库发现剩下的作业状态都变为了error。在尝试五分钟的延迟后,发现所有作业正常运行。原因还在排查中。
2.CronTrigger:基于日历的概念而不是精确的指定间隔进行重新启动的作业启动计划。