不知道大家在用Quartz的时候 有没有遇到这样一种情况:
触发器设定每3秒钟触发一次 ,但是工作需要10秒钟的执行时间.因此,在一次任务结束执行前,触发器已经错失触发
当这种情况下我们怎么处理呢,让我们一起学习一下......
还是先贴代码:
job类:StatefulDumbJob.java
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class StatefulDumbJob implements Job {
// 静态常量,作为任务在调用间,保持数据的键(key)
// NUM_EXECUTIONS,保存的计数每次递增1
// EXECUTION_DELAY,任务在执行时,中间睡眠的时间。本例中睡眠时间过长导致了错失触发
public static final String NUM_EXECUTIONS = "NumExecutions";
public static final String EXECUTION_DELAY = "ExecutionDelay";
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// 任务执行的时间
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
String jobRunTime = dateFormat.format(Calendar.getInstance().getTime());
System.err.println("---" + context.getJobDetail().getKey().getName() + " 在 : ["
+ jobRunTime + "] 执行了!!");
// 任务执行计数 累加
JobDataMap map = context.getJobDetail().getJobDataMap();
int executeCount = 0;
if (map.containsKey(NUM_EXECUTIONS)) {
executeCount = map.getInt(NUM_EXECUTIONS);
}
executeCount++;
map.put(NUM_EXECUTIONS, executeCount);
// 睡眠时间: 由调度类重新设置值 ,本例为 睡眠10s
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().getName()
+ " 完成次数 : " + executeCount );
}
}
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 java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
public class MisfireExample {
public static void main(String[] args) throws Exception {
MisfireExample example = new MisfireExample();
example.run();
}
public void run() throws Exception {
// 任务执行的时间 格式化
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
System.out.println("--------------- 初始化 -------------------");
// 下一个第15秒
Date startTime = nextGivenSecondDate(null, 15);
// statefulJob1 每3s运行一次,但它会延迟10s
JobDetail job = newJob(StatefulDumbJob.class)
.withIdentity("statefulJob1", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L) // 设置参数:睡眠时间 10s
.build();
SimpleTrigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.startAt(startTime)
.withSchedule(
simpleSchedule().withIntervalInSeconds(3)
.repeatForever()).build();
Date ft = sched.scheduleJob(job, trigger);
System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft)
+ " 时运行.并且重复: " + trigger.getRepeatCount() + " 次, 每次间隔 "
+ trigger.getRepeatInterval() / 1000 + " 秒");
// statefulJob2 将每3s运行一次 , 但它将延迟10s , 然后不断的迭代
job = newJob(StatefulDumbJob.class)
.withIdentity("statefulJob2", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)// 设置参数:睡眠时间 10s
.build();
trigger = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(
simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever()
// 设置错失触发后的调度策略
.withMisfireHandlingInstructionNowWithRemainingCount()
)
.build();
ft = sched.scheduleJob(job, trigger);
System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft)
+ " 时运行.并且重复: " + trigger.getRepeatCount() + " 次, 每次间隔 "
+ trigger.getRepeatInterval() / 1000 + " 秒");
System.out.println("------- 开始调度 (调用.start()方法) ----------------");
sched.start();
// 给任务留时间运行
Thread.sleep(600L * 1000L);
sched.shutdown(true);
System.out.println("------- 调度已关闭 ---------------------");
// 显示一下 已经执行的任务信息
SchedulerMetaData metaData = sched.getMetaData();
System.out.println("~~~~~~~~~~ 执行了 "
+ metaData.getNumberOfJobsExecuted() + " 个 jobs.");
}
}