
懒人兄弟们,哈哈哈……
接上篇正题。(本次终于干净利落了)
本范例演示如何打断正在执行中的任务。
任务被打断时,舍弃任务体的剩余部分,直接结束本次任务的执行,但是不影响下次触发。
1. DumbInterruptableJob.java
package com.zbaccp.quartz.cl.example7;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.InterruptableJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.UnableToInterruptJobException;
/**
* <p>
* 一个任务,实现了InterruptableJob接口,用户可以打断执行中的任务<br/>
* 所谓打断,意思是舍弃任务体未执行的部分,直接结束<br/>
* 只有实现InterruptableJob接口的任务,才有被打断的机制<br/>
* 而绝大多数的任务是不应当被打断的<br/>
* </p>
* @author 常磊
*/
public class DumbInterruptableJob implements InterruptableJob {
private static Log _log = LogFactory.getLog(DumbInterruptableJob.class);
// 标识,当值为true,结束execute()方法
private boolean _interrupted = false;
// 任务名
private String _jobName = "";
public DumbInterruptableJob() {
}
/**
* 任务体
*/
public void execute(JobExecutionContext context)
throws JobExecutionException {
_jobName = context.getJobDetail().getFullName();
_log.info("---- " + _jobName + " 开始时间: " + new Date());
try {
// 主任务循环,定期检查标识是否已经设置
// 如果是则舍弃任务的剩余部分,结束任务
for (int i = 0; i < 4; i++) {
try {
Thread.sleep(1000L);
} catch (Exception ignore) {
ignore.printStackTrace();
}
if (_interrupted) {
_log.info("--- " + _jobName
+ " -- 被打断... 放弃!");
//本处也可以抛异常,但是会影响其他请求被而尚未被打断的任务
//详细解释看Scheduler的interrupt()方法。
return;
}
}
} finally {
_log.info("---- " + _jobName + " 结束时间: " + new Date());
}
}
/**
* 当用户打断任务时,排程调用此方法,通知任务请求被打断
*/
public void interrupt() throws UnableToInterruptJobException {
_log.info("----- [被打断中] --");
_interrupted = true;
}
}
2. InterruptExample.java
package com.zbaccp.quartz.cl.example7;
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.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
/**
* 本范例演示任务的打断。只有实现InterruptableJob接口的任务,才有被打断的机制<br/>
* 打断的机制是这样,当用户打断任务时,排程调用任务的interrupt()方法,通知任务请求被打断。<br/>
* 一般来讲,任务体,也就是execute()方法,定期检查标识,看是否被请求打断,如果是则舍弃任务体剩余部分,结束本次任务。
*
* @author 常磊
*/
public class InterruptExample {
public void run() throws Exception {
final Log log = LogFactory.getLog(InterruptExample.class);
log.info("------- 开始初始化 ----------------------");
// 1 实例化排程
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
log.info("------- 初始化结束 -----------");
log.info("------- 安排任务 -------------------");
// 2 获取舍入的未来时间,以标识触发器的开始时间
long ts = TriggerUtils.getNextGivenSecondDate(null, 15).getTime();
// 3 将任务加入排程
JobDetail job = new JobDetail("interruptableJob1", "group1",
DumbInterruptableJob.class);
SimpleTrigger trigger = new SimpleTrigger("trigger1", "group1",
new Date(ts), null, SimpleTrigger.REPEAT_INDEFINITELY, 5000L);
Date ft = sched.scheduleJob(job, trigger);
log.info(job.getFullName() + " 运行时刻: " + ft + " 重复: "
+ trigger.getRepeatCount() + " 次,间隔 "
+ trigger.getRepeatInterval() / 1000 + " 秒");
// 4 排程开始运行
sched.start();
log.info("------- 启动排程 -----------------");
log
.info("------- 开始循环每7秒钟打断工作 ----------");
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(7000L);
// 5 排程打断任务
sched.interrupt(job.getName(), job.getGroup());
} catch (Exception e) {
}
}
log.info("------- 开始关闭 ---------------------");
// 6 开始关闭
sched.shutdown(true);
log.info("------- 关闭结束 -----------------");
SchedulerMetaData metaData = sched.getMetaData();
log.info("共执行工作 " + metaData.numJobsExecuted() + " 次");
}
public static void main(String[] args) throws Exception {
InterruptExample example = new InterruptExample();
example.run();
}
}
3. 我们的结论
l 调用排程的interrupt()打断任务时,任务的interrupt()被调用,任务如何被打断,依赖于任务本身的实现。我再重复一遍,排程只是调用任务的interrupt()方法。
l 本例任务的触发间隔是5秒钟,任务如果不被打断正常执行需要4秒钟。打断任务的主线程每7秒钟打断任务。因此不是所有的任务都会被打断。
[INFO] 25 六月 08:43:20.012 上午 DefaultQuartzScheduler_Worker-2
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
---- group1.interruptableJob1 开始时间: Sun Jun 25 08:43:20 CST 2006
[INFO] 25 六月 08:43:22.686 上午 main
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
----- [被打断中] --
[INFO] 25 六月 08:43:23.017 上午 DefaultQuartzScheduler_Worker-2
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
--- group1.interruptableJob1 -- 被打断... 放弃!
[INFO] 25 六月 08:43:23.017 上午 DefaultQuartzScheduler_Worker-2
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
---- group1.interruptableJob1 结束时间: Sun Jun 25 08:43:23 CST 2006
[DEBUG] 25 六月 08:43:25.010 上午
DefaultQuartzScheduler_QuartzSchedulerThread
[org.quartz.simpl.SimpleJobFactory]
Producing instance of Job ’group1.interruptableJob1’,
class=com.zbaccp.quartz.cl.example7.DumbInterruptableJob
[DEBUG] 25 六月 08:43:25.010 上午 DefaultQuartzScheduler_Worker-3
[org.quartz.core.JobRunShell]
Calling execute on job group1.interruptableJob1
[INFO] 25 六月 08:43:25.010 上午 DefaultQuartzScheduler_Worker-3
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
---- group1.interruptableJob1 开始时间: Sun Jun 25 08:43:25 CST 2006
[INFO] 25 六月 08:43:29.015 上午 DefaultQuartzScheduler_Worker-3
[com.zbaccp.quartz.cl.example7.DumbInterruptableJob]
---- group1.interruptableJob1 结束时间: Sun Jun 25 08:43:29 CST 2006
l 本次任务无论是否打断,都不影响下次触发,看上面代码中紫色部分,依然5秒钟后触发下次执行。
文件下载:quartzOfficial7.rar