Quartz总结
来源:互联网 发布:mac上将pdf转换成txt 编辑:程序博客网 时间:2024/06/05 16:26
前言
最近项目中有使用到Quartz,得空便总结总结,顺便记录一下这种设计模式,毕竟“好记性不如烂笔头”。
搭建
pom文件:
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version></dependency>
quartz.properties配置:
org.quartz.scheduler.instanceName = MySchedulerorg.quartz.threadPool.threadCount = 3org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
简单的示例
EnumCheckJobType,(官网:www.fhadmin.org)任务类型
public enum EnumCheckJobType { ONE,TWO }
SchedulerTask,任务的接口
public interface SchedulerTask { void run();}
OneScheduler,一个具体的任务
public class OneScheduler implements SchedulerTask{ @Override public void run() { //do something }}
TwoScheduler,另一个具体的任务
ublic class TwoScheduler implements SchedulerTask{ @Override public void run() { //do something }}
MyJob,执行任务(必须实现Job接口)
public class MyJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) { SchedulerTask task = (SchedulerTask) jobExecutionContext.getMergedJobDataMap().get("task"); task.run(); } }
MyScheduler,调度器(官网:www.fhadmin.org)(什么时候执行什么任务,指的是MyJob的execute方法)
public class MyScheduler { /** * 注册调度任务 * * @param scheduler * @param jobType * @param cronExpress cron 表达式 */ public void scheduleJob(Scheduler scheduler, EnumCheckJobType jobType, String cronExpress) { try { scheduleJob(scheduler, jobType, CronScheduleBuilder.cronSchedule(cronExpress)); } catch (SchedulerException e) { } } /** * 注册调度任务 * * @param scheduler * @param jobType(官网:www.fhadmin.org) * @param interval 间隔时间 */ public void scheduleJob(Scheduler scheduler, EnumCheckJobType jobType, int interval) { try { scheduleJob(scheduler, jobType, SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(interval) .repeatForever() .withMisfireHandlingInstructionNowWithExistingCount());//misfire策略 } catch (SchedulerException e) { } } /** * 注册调度任务 * * @param scheduler * @param jobType * @param builder */ public <T extends Trigger> void scheduleJob(Scheduler scheduler, EnumCheckJobType jobType, ScheduleBuilder<T> builder) throws SchedulerException { SchedulerTask task = newTask(jobType); if (task == null) { throw new SchedulerException(); } JobDetail job = JobBuilder.newJob(MyJob.class) .withIdentity(getJobName(jobType), getJobGroupName(jobType)) .build(); job.getJobDataMap().put("task", task); // 第二天的零点开始执行(官网:www.fhadmin.org) Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(getJobTriggerName(jobType), getJobGroupName(jobType)) .forJob(job.getKey()) .withSchedule(builder) .startAt(DateBuilder.tomorrowAt(0, 0, 0)) .build(); scheduler.scheduleJob(job, trigger); } private String getJobName(EnumCheckJobType checkType) { return checkType.name(); } private String getJobGroupName(EnumCheckJobType checkType) { return "group-" + checkType.name(); } private String getJobTriggerName(EnumCheckJobType jobType) { return jobType.name(); } private SchedulerTask newTask(EnumCheckJobType jobType) { switch (jobType) { case ONE: return applicationContext.getBean (OneScheduler.class); case TWO: return applicationContext.getBean (TwoScheduler.class); default: return null; } }}
HelloQuartz,主函数
public class HelloQuartz { public static void main(String[] args) throws SchedulerException { MyScheduler myScheduler = new MyScheduler(); try { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); myScheduler.scheduleJob(scheduler, EnumCheckJobType.ONE, "0 0 0 * * ?");//每天的凌晨0点执行 myScheduler.scheduleJob(scheduler, EnumCheckJobType.TWO, 60);//间隔60S执行一次 } catch (SchedulerException e) { } }}
Quartz的3个基本要素
- Scheduler:调度器。所有的调度都是由它控制。
- Trigger: 触发器。决定什么时候来执行任务。
- JobDetail & Job: JobDetail(官网:www.fhadmin.org) 定义的是任务数据,而真正的执行逻辑是在Job中。使用JobDetail + Job而不是Job,这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。
name和group
JobDetail和Trigger都有name和group。
name是它们在这个sheduler里面的唯一标识。如果我们要更新一个JobDetail定义,只需要设置一个name相同的JobDetail实例即可。
group是一个组织单元,sheduler会提供一些对整组操作的API,比如 scheduler.resumeJobs()。
misfire(错失触发)策略
当系统由于某种原因(未启动或是没有可用线程)在预定时刻没有启动任务,之后当系统可以调度该任务时(系统启动或是取得了可用线程),会首先检查当前时刻与预定时刻的差值,如果小于等于misfireThreshold值(该参数缺省为60秒),则不认为发生Misfire,并立刻启动该任务,一切正常进行。如果大于misfireThreshold值,则认为发生了misfire,此时的行为由trigger的Misfire Instructions来决定。而不同类型的trigger的缺省Misfire Instructions是不同的。
对于典型的SimpleTrigger:
缺省Misfire策略为Trigger.MISFIRE_INSTRUCTION_SMART_POLICY ,其他策略如下:
SimpleScheduleBuilder ssb = SimpleScheduleBuilder.simpleSchedule();ssb.withMisfireHandlingInstructionFireNow();//1ssb.withMisfireHandlingInstructionIgnoreMisfires();//2ssb.withMisfireHandlingInstructionNextWithExistingCount();//3ssb.withMisfireHandlingInstructionNextWithRemainingCount();//4ssb.withMisfireHandlingInstructionNowWithExistingCount();//5ssb.withMisfireHandlingInstructionNowWithRemainingCount();//6//1withMisfireHandlingInstructionFireNow ---> SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW (misfireInstruction == 1)——以当前时间为触发频率立即触发执行——执行至FinalTIme的剩余周期次数——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值//2withMisfireHandlingInstructionIgnoreMisfires ---> Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY(misfireInstruction == -1)—以错过的第一个频率时间立刻开始执行——重做错过的所有频率周期——当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率——共执行RepeatCount+1次//3withMisfireHandlingInstructionNextWithExistingCount ---> SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT(misfireInstruction == 5)——不触发立即执行——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数——以startTime为基准计算周期频率,并得到FinalTime——即使中间出现pause,resume以后保持FinalTime时间不变//4withMisfireHandlingInstructionNextWithRemainingCount ---> SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT(misfireInstruction == 4)——不触发立即执行——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数——以startTime为基准计算周期频率,并得到FinalTime——即使中间出现pause,resume以后保持FinalTime时间不变//5withMisfireHandlingInstructionNowWithExistingCount ---> SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT(misfireInstruction == 2)——以当前时间为触发频率立即触发执行——执行至FinalTIme的剩余周期次数——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值//6withMisfireHandlingInstructionNowWithRemainingCount ---> SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT(misfireInstruction == 3)——以当前时间为触发频率立即触发执行——执行至FinalTIme的剩余周期次数——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
基于在创建SimpleTrigger时选择的MISFIRE_INSTRUCTION_XXX更新SimpleTrigger的状态。 如果失火指令设置为MISFIRE_INSTRUCTION_SMART_POLICY,则将使用以下方案:
- 如果重复计数为0,则指令将解释为MISFIRE_INSTRUCTION_FIRE_NOW。
- 如果重复计数为REPEAT_INDEFINITELY(repeatForever),则指令将解释为MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT。 警告:如果触发器具有非空的结束时间,则使用MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT可能会导致触发器在失火时间范围内到达结束时,不会再次触发。
- 如果重复计数大于0,则指令将解释为MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT。
对于典型的CronTrigger:
缺省Misfire策略为Trigger.MISFIRE_INSTRUCTION_SMART_POLICY ,其他策略如下:
CronScheduleBuilder csb = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");csb.withMisfireHandlingInstructionDoNothing();csb.withMisfireHandlingInstructionFireAndProceed();csb.withMisfireHandlingInstructionIgnoreMisfires();withMisfireHandlingInstructionDoNothing ---> CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING(misfireInstruction = 2)——不触发立即执行——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行withMisfireHandlingInstructionFireAndProceed ---> CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW(misfireInstruction = 1)——以当前时间为触发频率立刻触发一次执行——然后按照Cron频率依次执行withMisfireHandlingInstructionIgnoreMisfires ---> Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY(misfireInstruction = -1)——以错过的第一个频率时间立刻开始执行——重做错过的所有频率周期后——当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
根据创建CronTrigger时选择的MISFIRE_INSTRUCTION_XXX更新CronTrigger的状态。 如果失火指令设置为MISFIRE_INSTRUCTION_SMART_POLICY,则将使用以下方案:
- 指令将解释为MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
- Quartz总结
- Quartz总结
- quartz配置总结
- 对quartz的总结
- quartz的总结
- Quartz.net使用总结
- Quartz使用示例总结
- quartz学习总结
- Quartz使用总结
- Quartz学习总结
- Quartz.net 入门 总结
- quartz学习bug总结
- Quartz 教程与总结
- quartz 2D 总结
- Quartz使用示例总结
- Quartz使用示例总结
- Quartz使用示例总结
- spring quartz 总结:
- AndroidUtils(二)Activity管理类
- mango
- 应用导向将是物联网低功耗广域网络主流模式
- Android图片加载框架最全解析(四),玩转Glide的回调与监听
- Android设计模式之(17)----代理模式
- Quartz总结
- 字体加载三种方式
- 前后台交互
- 设计模式的应用场景(22)--迭代器模式
- 持续集成利器-pipeline(一)
- HashTable和HashMap的区别详解
- 静态视图实体
- 欢迎使用CSDN-markdown编辑器
- Oracle数据库管理员的职责是什么?