感谢兄台: 《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暂停执行和继续执行的更多相关文章

  1. quartz2.3.0系列目录——带您由浅入深全面掌握quartz2.3.0

    quartz2.3.0系列目录 官网下载地址:http://www.quartz-scheduler.org/downloads/ 本系列demo全部来源于官网,仅仅是简化和汉化了注释!一部分代码de ...

  2. spring3.2.8+quartz2.2.0(比较全,对比quartz1.x的配置)

    spring3.2.8 + quartz2.2.0报错: java.lang.IncompatibleClassChangeError: class org.springframework.sched ...

  3. SpringBoot2.0.3整合Quartz2.3.0实现定时任务

    转载:https://www.cnblogs.com/ealenxie/p/9134602.html 关于别人写的quartz学习的地址:https://blog.csdn.net/lkl_csdn/ ...

  4. quartz2.3.0(十三)数据库持久化定时器job任务和trigger触发器,在多个调度器实例情况下,由其它调度器实例恢复执行调度器宕机的job任务

    一.初始化数据库11张quartz表:qrtz_*   先从官网下载好quartz2.3.0包:http://www.quartz-scheduler.org/downloads/ 解压后进入目录:q ...

  5. quartz2.3.0(十)xml配置方式定义quartz定时任务

    1.新增pom依赖 除了按照<quartz2.3.0系列目录——带您由浅入深全面掌握quartz2.3.0>添加依赖之外,pom.xml里新增加依赖: <dependency> ...

  6. 第七节:Trigger(SimpleTrigger、CronTrigger)哑火(MisFire)策略 :

    一. 简介 1. 什么是哑火 由于某些原因导致触发器(trigger)在该触发的时候没有得到触发,后续对应的解决策略即为哑火策略.(个人理解) 2. 哑火触发的条件 ①:所有的工作线程都在忙碌,导致某 ...

  7. Quartz任务调度:MisFire策略和源码分析

    Quartz是为大家熟知的任务调度框架,先看看官网的介绍: ---------------------------------------------------------------------- ...

  8. Quartz.Net系列(十六):Misfire策略在SimpleScheduler和CronScheduler中的使用

    1.场景 ①因为工作线程都在忙碌,所以导致某些Trigger得不到触发 也就是默认10个工作线程而我有15个Trigger同时触发 这就导致有5个不能被触发,而不幸的是Trigger所关联的Job执行 ...

  9. java线程池与五种常用线程池策略使用与解析

    背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...

随机推荐

  1. 59、Spark Streaming与Spark SQL结合使用之top3热门商品实时统计案例

    一.top3热门商品实时统计案例 1.概述 Spark Streaming最强大的地方在于,可以与Spark Core.Spark SQL整合使用,之前已经通过transform.foreachRDD ...

  2. windows环境搭建dubbo服务

    windows环境搭建dubbo服务 1:首先需要下载dubbo的注册中心 zookeeper zookeeper注册中心下载地址链接:http://mirror.bit.edu.cn/apache/ ...

  3. 集成了SSM框架的系统怎么做测试?

    1.首先在测试文件夹下新建一个测试基类BaseTest BaseTest中的代码如下: package wbl_ssm_blog.mapper; import org.junit.Test; impo ...

  4. 含有虚拟列的表 怎么用EXP导出?

    最近导一个测试库,报有虚拟列的表不支持,如下: EXP-00107: Feature (VIRTUAL COLUMN) of column CTB_CLIENT_SUBMIT_TIME_MONTH i ...

  5. 安装Nvidia显卡驱动、CUDA和cuDNN的方法(jsxyhelu整编)

    Nvidia显卡驱动.CUDA和cuDNN一般都是同时安装的,这里整理的是我成功运行的最简单的方法. 一.Nvidia显卡驱动 1.1 在可以进入图形界面的情况下 直接在"软件和更新&quo ...

  6. 阮一峰的ES6---Promise对象

    https://www.imooc.com/article/20580?block_id=tuijian_wz Promise的含义promise是异步编程的一种解决方法,比传统的回调函数和事件更合理 ...

  7. centos 宝塔面版 运行 thinkjs

    centos 宝塔面版 运行 thinkjs 几点要注意的地方: 1.  https ssl 如图 2. thinkjs 运行子目录在/www如图配置: 3. 代理配置(展示查看配置) server ...

  8. win10 mount error 112 : host is down解决方案

    摘自:https://www.baidu.com/link?url=xZrOVRqR9gqGRq0esfVaivByR9E5-ixyAuKsQ_8Hiedl1sY6J7ezBlgSW3oe_X-koo ...

  9. Hashmap(类似字典的东西)

    注意: 键值是唯一的,1个键对应一个值 常用api 打印处字典直接println方法 判断是否存在key值     containsKey() 例子: 基础操作 https://ke.qq.com/w ...

  10. Pytest单元测试框架-Pytest环境安装

    unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发 ...