quartz2.3.0(五)制定错过执行任务的misfire策略,用pause,resume模拟job暂停执行和继续执行
感谢兄台: 《quartz-misfire 错失、补偿执行》
misfire定义
misfire:被错过的执行任务策略
misfire重现——CronTrigger
job任务类:
package org.quartz.examples.example5; import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution; import java.text.SimpleDateFormat;
import java.util.Date; /**
* <pre>
* 任务job。
* 因为@DisallowConcurrentExecution注解,所以这个job不可以被多个定时器或触发器同时执行,否则会触发定时器的misfire,就需要我们定义好定时器的misfire策略。
* 如果不定义misfire,会出现
* </pre>
*/
@PersistJobDataAfterExecution //持久化JobDataMap里的数据,使下一个定时任务还能获取到这些值
@DisallowConcurrentExecution //禁止并发多任务执行,所以永远只有一个任务在执行中
public class StatefulDumbJob implements Job { //任务执行计数器
public static final String NUM_EXECUTIONS = "NumExecutions";
public static final String EXECUTION_DELAY = "ExecutionDelay";
public static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //必须要有public修饰的无参构造函数
public StatefulDumbJob() {
} //定时器执行方法
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("---" + context.getJobDetail().getKey() + " executing. [" + SDF.format(new Date()) + "]");
//获得带状态集合
JobDataMap map = context.getJobDetail().getJobDataMap(); int executeCount = 0;
if (map.containsKey(NUM_EXECUTIONS)) {
executeCount = map.getInt(NUM_EXECUTIONS);
} executeCount++; map.put(NUM_EXECUTIONS, executeCount); System.out.println(" -" + context.getJobDetail().getKey() + " complete (" + executeCount + ").[" + SDF.format(new Date())+ "]"); } }
定时器类:
package org.quartz.examples.example5; import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger; import java.util.Date; import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* <pre>
此类演示了如何定义定时器的misfire策略。misfire:被错过的执行任务策略
* </pre>
*/
public class MisfireExample_CronScheduleBuilder {
static final Logger LOG = LoggerFactory.getLogger(MisfireExample_CronScheduleBuilder.class); public static void main(String[] args) throws Exception {
// 初始化一个调度工厂,并实例化一个调度类
SchedulerFactory sf = new StdSchedulerFactory();
// Scheduler sched = sf.getScheduler();
StdScheduler sched = (StdScheduler) sf.getScheduler(); // 第一个参数:null就是默认当前时间,也可以指定时间
// 第二个参数:把一分钟按10进行划分,也就是60/10等份。
// 举例:当前时间是10:26:04,那么startTime就是10:30:00。当前时间是10:38:31,那么startTime就是10:40:00。
Date startTime = nextGivenSecondDate(null, 10);
JobDetail job = newJob(StatefulDumbJob.class).withIdentity("job1", "group1")
// .usingJobData(StatefulDumbJob.EXECUTION_DELAY, 30000L)
.build();
String cron = "0/2 * * * * ?"; // 每2秒执行一次 CronScheduleBuilder cronScheduleBuilder = cronSchedule(new CronExpression(cron)); // ========================================================================
// ======================== misfire定义,开始 =======================
// ======================================================================== /*
设置misfire策略:CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING = 2
——不触发立即执行
——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
*/
cronScheduleBuilder.withMisfireHandlingInstructionDoNothing(); /*
设置misfire策略:Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1
——以错过的第一个频率时间立刻开始执行 ——重做错过的所有频率周期 ——当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率
——共执行RepeatCount+1次
*/
// cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires(); /*
* 设置misfire策略:CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1
* 以当前时间为触发频率立刻触发一次执行,然后按照Cron频率依次执行
*/
// cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed(); // ========================================================================
// ======================== misfire定义,结束 =======================
// ======================================================================== CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(cronScheduleBuilder).build(); // CronTrigger默认misfire策略是: org.quartz.Trigger.MISFIRE_INSTRUCTION_SMART_POLICY = 0
int misfireInstruction = trigger.getMisfireInstruction();
LOG.info("当前misfire策略:" + misfireInstruction); Date ft = sched.scheduleJob(job, trigger);
LOG.info(job.getKey().toString()); sched.start();
LOG.info("调度器启动,主线程睡眠15秒!!!!调度器内任务线程继续执行。");
Thread.sleep(15L * 1000L); // // 暂停触发器
// sched.pauseTrigger(trigger.getKey());
// // 继续触发器
// sched.resumeTrigger(trigger.getKey()); // 暂停执行任务
sched.pauseJob(job.getKey());
LOG.info("调度器暂停执行定时器,主线程睡眠11秒!!!!会错过执行job1的N次定时任务。模拟当定时器的执行线程由于抢不到CPU时间或其他事件错过执行的情况。");
Thread.sleep(11L * 1000L);
// 继续执行任务
sched.resumeJob(job.getKey()); //当定时器得到继续执行的命令时,被错过执行的任务次数,就会按照misfire的定义去执行 LOG.info("调度器继续执行定时器,主线程睡眠15秒!!!!调度器内任务线程继续执行。");
Thread.sleep(15L * 1000L); LOG.info("调度器终止执行!!!!");
sched.shutdown(true);
} }
misfire重现——SimpleTrigger
CronTrigger的misfire策略经本人亲自测试,注释全部可靠,SimpleTrigger全部来自以下兄台文章注释,实际结果请各位亲自实验。
感谢兄台: 《quartz-misfire 错失、补偿执行》
SimpleTrigger默认misfire策略也是: org.quartz.Trigger.MISFIRE_INSTRUCTION_SMART_POLICY = 0
//定义触发器,2秒执行一次,循环5次,总共执行6次
SimpleScheduleBuilder simpleScheduleBuilder = simpleSchedule().withIntervalInSeconds(2).withRepeatCount(5);
// .repeatForever(); //无限循环 /*
设置misfire策略为:SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5
——不触发立即执行
——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
——以startTime为基准计算周期频率,并得到FinalTime
——即使中间出现pause,resume以后保持FinalTime时间不变
*/
simpleScheduleBuilder.withMisfireHandlingInstructionNextWithExistingCount(); /*
设置misfire策略为:SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4
——不触发立即执行
——等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
——以startTime为基准计算周期频率,并得到FinalTime
——即使中间出现pause,resume以后保持FinalTime时间不变
*/
simpleScheduleBuilder.withMisfireHandlingInstructionNextWithRemainingCount(); /*
设置misfire策略为:SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
*/
simpleScheduleBuilder.withMisfireHandlingInstructionNowWithRemainingCount(); /*
设置misfire策略为:SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
*/
simpleScheduleBuilder.withMisfireHandlingInstructionNowWithExistingCount(); /*
设置misfire策略为:SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW = 1
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
*/
simpleScheduleBuilder.withMisfireHandlingInstructionFireNow(); /*
设置misfire策略为:Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1
——以错过的第一个频率时间立刻开始执行
——重做错过的所有频率周期
——当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率
——共执行RepeatCount+1次
*/
simpleScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
quartz2.3.0(五)制定错过执行任务的misfire策略,用pause,resume模拟job暂停执行和继续执行的更多相关文章
- quartz2.3.0系列目录——带您由浅入深全面掌握quartz2.3.0
quartz2.3.0系列目录 官网下载地址:http://www.quartz-scheduler.org/downloads/ 本系列demo全部来源于官网,仅仅是简化和汉化了注释!一部分代码de ...
- spring3.2.8+quartz2.2.0(比较全,对比quartz1.x的配置)
spring3.2.8 + quartz2.2.0报错: java.lang.IncompatibleClassChangeError: class org.springframework.sched ...
- SpringBoot2.0.3整合Quartz2.3.0实现定时任务
转载:https://www.cnblogs.com/ealenxie/p/9134602.html 关于别人写的quartz学习的地址:https://blog.csdn.net/lkl_csdn/ ...
- quartz2.3.0(十三)数据库持久化定时器job任务和trigger触发器,在多个调度器实例情况下,由其它调度器实例恢复执行调度器宕机的job任务
一.初始化数据库11张quartz表:qrtz_* 先从官网下载好quartz2.3.0包:http://www.quartz-scheduler.org/downloads/ 解压后进入目录:q ...
- quartz2.3.0(十)xml配置方式定义quartz定时任务
1.新增pom依赖 除了按照<quartz2.3.0系列目录——带您由浅入深全面掌握quartz2.3.0>添加依赖之外,pom.xml里新增加依赖: <dependency> ...
- 第七节:Trigger(SimpleTrigger、CronTrigger)哑火(MisFire)策略 :
一. 简介 1. 什么是哑火 由于某些原因导致触发器(trigger)在该触发的时候没有得到触发,后续对应的解决策略即为哑火策略.(个人理解) 2. 哑火触发的条件 ①:所有的工作线程都在忙碌,导致某 ...
- Quartz任务调度:MisFire策略和源码分析
Quartz是为大家熟知的任务调度框架,先看看官网的介绍: ---------------------------------------------------------------------- ...
- Quartz.Net系列(十六):Misfire策略在SimpleScheduler和CronScheduler中的使用
1.场景 ①因为工作线程都在忙碌,所以导致某些Trigger得不到触发 也就是默认10个工作线程而我有15个Trigger同时触发 这就导致有5个不能被触发,而不幸的是Trigger所关联的Job执行 ...
- java线程池与五种常用线程池策略使用与解析
背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...
随机推荐
- uni app 零基础小白到项目实战-1
uni-app是一个使用vue.js开发跨平台应用的前端框架. 开发者通过编写vue.js代码,uni-app将其编译到Ios,android,微信小程序等多个平台,保证其正确并达到优秀体验. Uni ...
- pycharm+gitee环境搭建(超详细)
背景:本地开发代码在没有云托管的时候代码很容易丢掉,如果是小团队,这时候可以使用公司团队注册一个账号共同使用.如果是个人用于代码存储或者用于以后项目经验也推荐gitee.大的团队可以购买 环境:win ...
- 微信小程序 base64格式图片的显示及保存
当我们拿到如下base64格式的图片(如下图)时, base64格式的图片数据: 如何显示 ? 使用image标签,src属性添加data:image/png;base64, (注意:若imgData ...
- element ui分页器的使用
<el-pagination layout="total, prev, pager, next, jumper" :current-page="pageInfo.p ...
- rust 函数的使用
fn main() { println!("Hello, world!"); another_function(2,3); let y ={ let x =3; //表达式的结尾没 ...
- Spring Cloud Feign踩坑记录(二)
注意,以下的Feign遇到的坑,在高版本中有些已经修复. 某些项目由于历史包袱原因,无法进行全面升级,才需要修补这些坑. 1.启动报错:not annotated with HTTP method t ...
- if, if/else, if /elif/else,case
一.if语句用法 if expression then command fi 例子:使用整数比较运算符 read -p "please input a integer:" a if ...
- assert(0)的作用
捕捉逻辑错误.可以在程序逻辑必须为真的条件上设置断言.除非发生逻辑错误,否则断言对程序无任何影响.即预防性的错误检查,在认为不可能的执行到的情况下加一句ASSERT(0),如果运行到此,代码逻辑或条件 ...
- uniapp - 关于ios调试
[ios调试] 1.一台windows电脑.一根apple数据线(一旦连接以后,apple设备就会自动识别itunes软件,如果没有安装会提示) 2.安装itunes (爱思助手) 3.官方教程:ht ...
- MSYS2 常见操作
博客转自:http://www.cnblogs.com/vincenzo/archive/2010/05/13/1734230.html 和 https://blog.csdn.net/langres ...