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 ...
随机推荐
- 开源项目 07 AutoMapper
using AutoMapper; using Newtonsoft.Json; using System; using System.Collections.Generic; using Syste ...
- C# DataTable转换为Html
/// <summary> /// DataTable 转换为 Html /// </summary> /// <param name="dt"> ...
- Linux 服务器快速搭建 Java Web 开发环境
搭建 Java 环境 yum list java* yum install java-1.8.0-openjdk.x86_64 -y java -version mkdir 创建文件夹 mv 修改文件 ...
- 用Visual Studio编写UDF的一点小技巧(二)
- java下载文件工具类
java下载文件工具类 package com.skjd.util; import java.io.BufferedInputStream; import java.io.BufferedOutput ...
- pdfBox 解析 pdf文件
Spting boot 项目 1.添加依赖 <dependency> <groupId>org.apache.pdfbox</groupId> <artifa ...
- 第07组 Beta冲刺(2/5)
队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:代码编辑器 展示GitHub当日代码/文档签入记录:(组内共用,已询问过助教小姐姐) ...
- word 转 pdf,c#代码
通过使用 C# 控制 office 软件 com 组件转 pdf 1 word 转 pdf 方案二:可以使用 netoffice 进行转换 参考文档:https://netoffice.io/docu ...
- Python高级笔记(十一)装饰器【面试】
1. 需求 开发封闭原则:虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被拓展,即: 封闭:已实现的功能代码块 开发:对拓展开发 2. ...
- Python 初级 6 循环
一.一个简单的for循环 1 重复做相同的事 for looper in [1, 2, 3, 4, 5]: print("hello") 1 looper的值从1开始, 所以loo ...