Quartz 之 Job Misfires
Posted 秋风小凉鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz 之 Job Misfires相关的知识,希望对你有一定的参考价值。
项目地址:
https://github.com/yuleiqq/quartz_example/tree/master/quartz_study
此示例旨在演示与触发错误触发相关的概念。
程序将执行以下操作:
- 启动Quartz 调度器
- 计划两个作业,每个作业将无限期地每三秒钟执行一次
- 运行作业需要10秒(防止执行触发器每三秒触发一次)
-
每个作业都有不同的失败指令
-
程序将等待10分钟,以便两个作业有足够的时间运行
-
停止调度器
代码有如下类组成:
类名 | 描述 |
MisfireExample | 主程序 |
StatefulDumbJob | 运行一个简单的job类,它的execute方法需要10秒钟 |
StatefulDumbJob
StatefulDumbJob是一个简单的作业,它打印它的执行时间,然后在完成之前等待一段时间。
等待时间量由作业参数EXECUTION_DELAY定义。如果没有传入此作业参数,则该作业将默认为5秒的等待时间。该作业还保留自己的计数,即使用其JobDataMap中名为num_的值执行了多少次。因为该类具有PersistJobDataAfterExecution注释,所以在每次执行之间保留执行计数。
package com.example06;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
/**
* @author : yulei
* @data : 2020/5/21 21:18
* @Version : 1.0
**/
public class StatefulDumbJob implements Job
//执行次数累计
public static final String NUM_EXECUTIONS = "NumExecutions";
//延迟执行时间
public static final String EXECUTION_DELAY = "ExecutionDelay";
public StatefulDumbJob()
public void execute(JobExecutionContext context) throws JobExecutionException
System.err.println("---" + context.getJobDetail().getKey()
+ " executing.[" + 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);
long delay = 5000l;
if (map.containsKey(EXECUTION_DELAY))
delay = map.getLong(EXECUTION_DELAY);
try
Thread.sleep(delay);
catch (Exception ignore)
System.err.println(" -" + context.getJobDetail().getKey()
+ " complete (" + executeCount + ").");
MisfireExample
程序首先获取调度程序的一个实例。这是通过创建一个StdSchedulerFactory来完成的,然后使用它来创建一个调度器。这将创建一个简单的基于RAM的调度器,因为没有特定的 quartz.properties配置文件 告诉它执行其他操作。
package com.example06;
import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
/**
* @author : yulei
* @data : 2020/5/21 21:30
* @Version : 1.0
**/
public class MisfireExample
public void run() throws Exception
Logger log = LoggerFactory.getLogger(MisfireExample.class);
log.info("------- Initializing -------------------");
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
log.info("------- Initialization Complete -----------");
Date startTime = nextGivenSecondDate(null, 15);
//statefulJob1 3秒钟执行一次 (但是会延迟10秒)
JobDetail job = newJob(StatefulDumbJob.class).withIdentity("statefulJob1", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();
SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();
Date ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
+ trigger.getRepeatInterval() / 1000 + " seconds");
// statefulJob2每三秒钟运行一次
//(但是它会延迟10秒—因此在几次迭代之后故意失火)
job = newJob(StatefulDumbJob.class).withIdentity("statefulJob2", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();
trigger = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()
.withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instructions
.build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
+ trigger.getRepeatInterval() / 1000 + " seconds");
log.info("------- Starting Scheduler ----------------");
sched.start();
log.info("------- Started Complete -----------------");
try
// sleep for ten minutes for triggers to file....
Thread.sleep(600L * 1000L);
catch (Exception e)
//
log.info("------- Shutting Down ---------------------");
sched.shutdown(true);
log.info("------- Shutdown Complete -----------------");
SchedulerMetaData metaData = sched.getMetaData();
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
public static void main(String[] args) throws Exception
MisfireExample example = new MisfireExample();
example.run();
withMisfireHandlingInstructionNowWithExistingCount
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
执行后,运行结果如下:
--group1.statefulJob1 executing.[Thu May 21 22:07:15 CST 2020]
---group1.statefulJob2 executing.[Thu May 21 22:07:15 CST 2020]
-group1.statefulJob1 complete (1).
-group1.statefulJob2 complete (1).
---group1.statefulJob2 executing.[Thu May 21 22:07:25 CST 2020]
---group1.statefulJob1 executing.[Thu May 21 22:07:27 CST 2020]
-group1.statefulJob2 complete (2).
---group1.statefulJob2 executing.[Thu May 21 22:07:35 CST 2020]
-group1.statefulJob1 complete (2).
---group1.statefulJob1 executing.[Thu May 21 22:07:39 CST 2020]
-group1.statefulJob2 complete (3).
---group1.statefulJob2 executing.[Thu May 21 22:07:45 CST 2020]
-group1.statefulJob1 complete (3).
---group1.statefulJob1 executing.[Thu May 21 22:07:51 CST 2020]
-group1.statefulJob2 complete (4).
---group1.statefulJob2 executing.[Thu May 21 22:07:55 CST 2020]
-group1.statefulJob1 complete (4).
---group1.statefulJob1 executing.[Thu May 21 22:08:03 CST 2020]
-group1.statefulJob2 complete (5).
---group1.statefulJob2 executing.[Thu May 21 22:08:05 CST 2020]
可以看到 job2 在延迟10秒之后是立即执行的. 而 job1 还是按照 正常的3秒一次执行,错过上次频率,会在下次触发频率开始执行.
以上是关于Quartz 之 Job Misfires的主要内容,如果未能解决你的问题,请参考以下文章