how2j.cn

下载区
文件名 文件大小
quartz.rar 1m
使用站长秘制下载工具
步骤 1 : Job 组成部分   
步骤 2 : Job 并发   
步骤 3 : Job 异常   
步骤 4 : 中断 Job   

Job 其实是由 3 个部分组成:
JobDetail: 用于描述这个Job是做什么的
实现Job的类: 具体干活的
JobDataMap: 给 Job 提供参数用的

JobDataMap 除了usingJobData 方式之外,还可以是其他方式,像这样

job.getJobDataMap().put("email", "admin@taobao.com");
package com.how2java; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import org.quartz.InterruptableJob; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class TestQuartz { public static void main(String[] args) throws Exception{ jobDataMap(); } private static void jobDataMap() throws SchedulerException, InterruptedException { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(MailJob.class) .withIdentity("mailjob1", "mailgroup") .usingJobData("email", "admin@10086.com") .build(); //用JobDataMap 修改email job.getJobDataMap().put("email", "admin@taobao.com"); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } }
默认的情况下,无论上一次任务是否结束或者完成,只要规定的时间到了,那么下一次就开始。

有时候会做长时间的任务,比如数据库备份,这个时候就希望上一次备份成功结束之后,才开始下一次备份,即便是规定时间到了,也不能开始,因为这样很有可能造成 数据库被锁死 (几个线程同时备份数据库,引发无法预计的混乱)。

那么在这种情况下,给数据库备份任务增加一个注解就好了:

@DisallowConcurrentExecution
package com.how2java; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @DisallowConcurrentExecution public class DatabaseBackupJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { JobDetail detail = context.getJobDetail(); String database = detail.getJobDataMap().getString("database"); System.out.printf("给数据库 %s 备份, 耗时10秒 %n" ,database); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.how2java; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import org.quartz.InterruptableJob; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class TestQuartz { public static void main(String[] args) throws Exception{ // jobDataMap(); databaseCurrentJob(); } private static void databaseCurrentJob() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(DatabaseBackupJob.class) .withIdentity("backupjob", "databasegroup") .usingJobData("database", "how2java") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待200秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(200000); scheduler.shutdown(true); } private static void jobDataMap() throws SchedulerException, InterruptedException { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(MailJob.class) .withIdentity("mailjob1", "mailgroup") .usingJobData("email", "admin@10086.com") .build(); //用JobDataMap 修改email job.getJobDataMap().put("email", "admin@taobao.com"); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } }
任务里发生异常是很常见的。 异常处理办法通常是两种:
1. 当异常发生,那么就通知所有管理这个 Job 的调度,停止运行它
2. 当异常发生,修改一下参数,马上重新运行
package com.how2java; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class ExceptionJob1 implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { int i = 0; try { //故意发生异常 System.out.println(100/i); } catch (Exception e) { System.out.println("发生了异常,取消这个Job 对应的所有调度"); JobExecutionException je =new JobExecutionException(e); je.setUnscheduleAllTriggers(true); throw je; } } }
package com.how2java; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class ExceptionJob2 implements Job { static int i = 0; public void execute(JobExecutionContext context) throws JobExecutionException { try { //故意发生异常 System.out.println("运算结果"+100/i); } catch (Exception e) { System.out.println("发生了异常,修改一下参数,立即重新执行"); i = 1; JobExecutionException je =new JobExecutionException(e); je.setRefireImmediately(true); throw je; } } }
package com.how2java; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import org.quartz.InterruptableJob; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class TestQuartz { public static void main(String[] args) throws Exception{ // jobDataMap(); // databaseCurrentJob(); exceptionHandle1(); // exceptionHandle2(); } private static void exceptionHandle2() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(ExceptionJob2.class) .withIdentity("exceptionJob1", "someJobGroup") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } private static void exceptionHandle1() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(ExceptionJob1.class) .withIdentity("exceptionJob1", "someJobGroup") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } private static void databaseCurrentJob() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(DatabaseBackupJob.class) .withIdentity("backupjob", "databasegroup") .usingJobData("database", "how2java") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待200秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(200000); scheduler.shutdown(true); } private static void jobDataMap() throws SchedulerException, InterruptedException { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(MailJob.class) .withIdentity("mailjob1", "mailgroup") .usingJobData("email", "admin@10086.com") .build(); //用JobDataMap 修改email job.getJobDataMap().put("email", "admin@taobao.com"); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } }
在业务上,有时候需要中断任务,那么这个Job需要实现 InterruptableJob 接口,然后就方便中断了
package com.how2java; import org.quartz.InterruptableJob; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.UnableToInterruptJobException; //必须实现InterruptableJob 而非 Job才能够被中断 public class StoppableJob implements InterruptableJob { private boolean stop = false; public void execute(JobExecutionContext context) throws JobExecutionException { while(true){ if(stop) break; try { System.out.println("每隔1秒,进行一次检测,看看是否停止"); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("持续工作中。。。"); } } public void interrupt() throws UnableToInterruptJobException { System.out.println("被调度叫停"); stop = true; } }
package com.how2java; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import org.quartz.InterruptableJob; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class TestQuartz { public static void main(String[] args) throws Exception{ // jobDataMap(); // databaseCurrentJob(); // exceptionHandle1(); // exceptionHandle2(); stop(); } private static void stop() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .build(); //定义一个JobDetail JobDetail job = newJob(StoppableJob.class) .withIdentity("exceptionJob1", "someJobGroup") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); Thread.sleep(5000); System.out.println("过5秒,调度停止 job"); //key 就相当于这个Job的主键 scheduler.interrupt(job.getKey()); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } private static void exceptionHandle2() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(ExceptionJob2.class) .withIdentity("exceptionJob1", "someJobGroup") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } private static void exceptionHandle1() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(ExceptionJob1.class) .withIdentity("exceptionJob1", "someJobGroup") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } private static void databaseCurrentJob() throws Exception { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(DatabaseBackupJob.class) .withIdentity("backupjob", "databasegroup") .usingJobData("database", "how2java") .build(); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待200秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(200000); scheduler.shutdown(true); } private static void jobDataMap() throws SchedulerException, InterruptedException { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(10)) .build(); //定义一个JobDetail JobDetail job = newJob(MailJob.class) .withIdentity("mailjob1", "mailgroup") .usingJobData("email", "admin@10086.com") .build(); //用JobDataMap 修改email job.getJobDataMap().put("email", "admin@taobao.com"); //调度加入这个job scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); //等待20秒,让前面的任务都执行完了之后,再关闭调度器 Thread.sleep(20000); scheduler.shutdown(true); } }


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2018-09-03 interrupt
158962125




中断是不是只适用于执行一次的Job任务?好像多次执行的不管用
Trigger trigger = newTrigger().withIdentity("trigger1", "group1")
            .startNow()
            .withSchedule(simpleSchedule()
                .withIntervalInSeconds(2)
                .withRepeatCount(10))
            .build();

							


1 个答案

158962125
答案时间:2018-09-03
另外,中断是不是就是调用Job的interrupt方法而已,并没有真正停止执行,而是要自己通过设置标志位来控制???



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2018-07-30 中断job 那里
iloveyou无望

把 Thread.sleep(20000); 这段代码注释掉 看的更清晰







回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2018-05-24 interrupt定义时没参数,使用时有参数,什么鬼?
2018-03-29 main的线程和调度的excute是不是 不是一个线程啊 不然怎么会调度停止job了还会持续工作中。。。




提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 工具和中间件-quartz-Job 管理 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 745032160
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图