Shows how the scheduler can interrupt your jobs and how to code your jobs to deal with interruptions
由于业务需要,中断Quartz中正在执行的任务,需要实现以下步骤:
- Job类需要实现InterruptableJob类,并实现interrupt()方法
- 在interrupt()方法中通常设定一个interrupted 变量为ture(默认时为false)实现从外界传递中断的指令。
- 在这个方法中进行了标记的改变,在execute()方法对这个标记判断,以实现中断任务,如:return,或抛出一个JobExecutionException异常
- 在调度器上调用方法:sched.interrupt(job.getKey()),它最终是执行Job中的interrupt()方法。
scheduler如何改变在Job中的interrupted 为true,实现原理:
1.执行sched.interrupt(job.getKey()),希望这个Job任务中断
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(7000L);
// tell the scheduler to interrupt our job
sched.interrupt(job.getKey());
} catch (Exception e) {
//
}
}
2.可以看到实际执行的是sched.interrupt(jobKey)
public boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException {
return sched.interrupt(jobKey);
}
3.我再往下看interrupt(JobKey jobKey)的源码
可以注意到,其中有一句 ((InterruptableJob)job).interrupt();
相当真正执行的是job(实现了InterruptableJob)这个类实际的interrupt()中的代码。
而这个job对象是由我们每一步传入的,是我们要中断的Job,故这里相当于执行要中断的Job的interrupt()中的代码。
/**
* Interrupt all instances of the identified InterruptableJob executing in
* this Scheduler instance.
*
* <p>
* This method is not cluster aware. That is, it will only interrupt
* instances of the identified InterruptableJob currently executing in this
* Scheduler instance, not across the entire cluster.
* </p>
*
* @see org.quartz.core.RemotableQuartzScheduler#interrupt(JobKey)
*/
public boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException {
List<JobExecutionContext> jobs = getCurrentlyExecutingJobs();
JobDetail jobDetail = null;
Job job = null;
boolean interrupted = false;
for(JobExecutionContext jec : jobs) {
jobDetail = jec.getJobDetail();
if (jobKey.equals(jobDetail.getKey())) {
job = jec.getJobInstance();
if (job instanceof InterruptableJob) {
((InterruptableJob)job).interrupt();
interrupted = true;
} else {
throw new UnableToInterruptJobException(
"Job " + jobDetail.getKey() +
" can not be interrupted, since it does not implement " +
InterruptableJob.class.getName());
}
}
}
return interrupted;
}
4.在实现了InterruptableJob的这个我们传入进去的,Job实现的interrupt()方法,我们修改了 _interrupted = true;
Job中就可以用 _interrupted 这个变量的值来判断外界有没有发出中断指令了。
执行 interrupt() 后,_interrupted发生了变量,在execute()方法中就可以用这个值来判断外界有无发出中断指令,然后就可以用这个值来做事了,如return,或抛出一个JobExecutionException异常
package org.quartz.examples.example7;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.InterruptableJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.UnableToInterruptJobException;
/**
* <p>
* A dumb implementation of an InterruptableJob, for unit testing purposes.
* </p>
*
<