# 示例7 - 中断作业

说明

此示例演示调度程序如何中断作业,以及如何对作业进行编码以处理中断。

# DumbInterruptableJob.java源码

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;


/**
 * 用于单元测试的InterruptableJob的缺陷实现
 * 作者:Chris Bonham
 * 作者:Bill Kratzer
 */
public class DumbInterruptableJob implements InterruptableJob {
    
    //日志服务
    private static Logger _log = LoggerFactory.getLogger(DumbInterruptableJob.class);
    
    //作业中断了吗?
    private boolean _interrupted = false;

    //作业名称 
    private JobKey _jobKey = null;
    
    /**
     * 用于作业初始化的空参构造函数
     */
    public DumbInterruptableJob() {
    }


    /**
     * 当与此作业相关联的触发器触发时,由调度器调用此方法
     * Throws:作业执行异常(JobExecutionException)-当执行作业时产生异常
     */
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        _jobKey = context.getJobDetail().getKey();
        _log.info("---- " + _jobKey + " executing at " + new Date());

        try {
            //主作业循环…有关讨论,请参阅InterruptibleJob的Java文档…
            //做一些工作…在这个例子中,我们通过睡觉来“模拟”工作…
            for (int i = 0; i < 4; i++) {
                try {
                    Thread.sleep(1000L);
                } catch (Exception ignore) {
                    ignore.printStackTrace();
                }
                
                //定期检查我们是否被打断了…
                if(_interrupted) {
                    _log.info("--- " + _jobKey + "  -- Interrupted... bailing out!");
                    return; //也可以选择抛出作业执行异常,如果这基于特定工作的职责/行为是合理的
                }
            }
            
        } finally {
            _log.info("---- " + _jobKey + " completed at " + new Date());
        }
    }
    
    /**
     * 当用户中断作业时由调度器调用
     * 
     * @return void (nothing) 如果作业中断成功
     * @throws JobExecutionException 如果中断作业时出现异常    
     */
    public void interrupt() throws UnableToInterruptJobException {
        _log.info("---" + _jobKey + "  -- INTERRUPTING --");
        _interrupted = true;
    }

}

# InterruptExample.java源码

package org.quartz.examples.example7;

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.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;

/**
 * 演示StatefulJobs的行为,以及当作业执行时间超过触发器重复频率时,失误指令如何影响StatefulJobs触发器的触发。
 * 在运行此示例时,您应该注意到有两个具有相同计划的触发器,它们触发相同的作业。触发器“希望”每3秒触发1次,但作业需要10秒才能执
 * 行。因此,当作业完成执行时,触发器已经“失误”(除非调度程序的“失误阈值”设置为超过7秒)。您应该看到其中一个作业的失误指令设置为
 * SimpleTrigger。
 * MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT—当检测到失误时,它会立即触发。另一个触发器使用默认
 * 的“智能策略”失误指令,这会导致触发器提前到下一个触发时间(跳过错过的那些),这样它不会立即重新触发,而是等到下一个计划时间。
 * 作者:Chris Bonham
 */
public class InterruptExample {

  public void run() throws Exception {
    final Logger log = LoggerFactory.getLogger(InterruptExample.class);

    log.info("------- Initializing ----------------------");

    //首先,我们必须获得对调度器的引用
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = sf.getScheduler();

    log.info("------- Initialization Complete -----------");

    log.info("------- Scheduling Jobs -------------------");

    //在未来15秒后获得1次不错的轮转时间(开始执行所有作业)
    Date startTime = nextGivenSecondDate(null, 15);

    JobDetail job = newJob(DumbInterruptableJob.class).withIdentity("interruptableJob1", "group1").build();

    SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
        .withSchedule(simpleSchedule().withIntervalInSeconds(5).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");

    //开启调度器(在调度器启动之前,所有作业都不会执行)
    sched.start();
    log.info("------- Started Scheduler -----------------");

    log.info("------- Starting loop to interrupt job every 7 seconds ----------");
    for (int i = 0; i < 50; i++) {
      try {
        Thread.sleep(7000L);
        //通知调度器中断作业
        sched.interrupt(job.getKey());
      } 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 {

    InterruptExample example = new InterruptExample();
    example.run();
  }

}

# 控制台输出

[main] INFO org.quartz.examples.example7.InterruptExample - ------- Initializing ----------------------
[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.examples.example7.InterruptExample - ------- Initialization Complete -----------
[main] INFO org.quartz.examples.example7.InterruptExample - ------- Scheduling Jobs -------------------
[main] INFO org.quartz.examples.example7.InterruptExample - group1.interruptableJob1 will run at: Thu Dec 01 21:35:30 CST 2022 and repeat: -1 times, every 5 seconds
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
[main] INFO org.quartz.examples.example7.InterruptExample - ------- Started Scheduler -----------------
[main] INFO org.quartz.examples.example7.InterruptExample - ------- Starting loop to interrupt job every 7 seconds ----------
[DefaultQuartzScheduler_Worker-1] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:30 CST 2022
[DefaultQuartzScheduler_Worker-1] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 completed at Thu Dec 01 21:35:34 CST 2022
[DefaultQuartzScheduler_Worker-2] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:35 CST 2022
[main] INFO org.quartz.examples.example7.DumbInterruptableJob - ---group1.interruptableJob1  -- INTERRUPTING --
[DefaultQuartzScheduler_Worker-2] INFO org.quartz.examples.example7.DumbInterruptableJob - --- group1.interruptableJob1  -- Interrupted... bailing out!
[DefaultQuartzScheduler_Worker-2] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 completed at Thu Dec 01 21:35:37 CST 2022
[DefaultQuartzScheduler_Worker-3] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:40 CST 2022
[main] INFO org.quartz.examples.example7.DumbInterruptableJob - ---group1.interruptableJob1  -- INTERRUPTING --
[DefaultQuartzScheduler_Worker-3] INFO org.quartz.examples.example7.DumbInterruptableJob - --- group1.interruptableJob1  -- Interrupted... bailing out!
[DefaultQuartzScheduler_Worker-3] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 completed at Thu Dec 01 21:35:44 CST 2022
[DefaultQuartzScheduler_Worker-4] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:45 CST 2022
[DefaultQuartzScheduler_Worker-4] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 completed at Thu Dec 01 21:35:49 CST 2022
[DefaultQuartzScheduler_Worker-5] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:50 CST 2022
[main] INFO org.quartz.examples.example7.DumbInterruptableJob - ---group1.interruptableJob1  -- INTERRUPTING --
[DefaultQuartzScheduler_Worker-5] INFO org.quartz.examples.example7.DumbInterruptableJob - --- group1.interruptableJob1  -- Interrupted... bailing out!
[DefaultQuartzScheduler_Worker-5] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 completed at Thu Dec 01 21:35:51 CST 2022
[DefaultQuartzScheduler_Worker-6] INFO org.quartz.examples.example7.DumbInterruptableJob - ---- group1.interruptableJob1 executing at Thu Dec 01 21:35:55 CST 2022
[main] INFO org.quartz.examples.example7.DumbInterruptableJob - ---group1.interruptableJob1  -- INTERRUPTING --
[DefaultQuartzScheduler_Worker-6] INFO org.quartz.examples.example7.DumbInterruptableJob - --- group1.interruptableJob1  -- Interrupted... bailing out!

微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。