Quartz 之 Job Misfires

项目地址:  

         https://github.com/yuleiqq/quartz_example/tree/master/quartz_study

此示例旨在演示与触发错误触发相关的概念。

程序将执行以下操作:

  • 启动Quartz 调度器
  • 计划两个作业,每个作业将无限期地每三秒钟执行一次
  • 运行作业需要10秒(防止执行触发器每三秒触发一次)
  • 每个作业都有不同的失败指令

  • 程序将等待10分钟,以便两个作业有足够的时间运行

  • 停止调度器

代码有如下类组成:

类名描述
MisfireExample主程序
StatefulDumbJob运行一个简单的job类,它的execute方法需要10秒钟

 

StatefulDumbJob

StatefulDumbJob是一个简单的作业,它打印它的执行时间,然后在完成之前等待一段时间。

等待时间量由作业参数EXECUTION_DELAY定义。如果没有传入此作业参数,则该作业将默认为5秒的等待时间。该作业还保留自己的计数,即使用其JobDataMap中名为num_的值执行了多少次。因为该类具有PersistJobDataAfterExecution注释,所以在每次执行之间保留执行计数。

package com.example06;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * @author :  yulei
 * @data :  2020/5/21 21:18
 * @Version :  1.0
 **/

public class StatefulDumbJob  implements Job {

    //执行次数累计
    public static final String NUM_EXECUTIONS = "NumExecutions";
    //延迟执行时间
    public static final String EXECUTION_DELAY = "ExecutionDelay";

    public StatefulDumbJob() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.err.println("---" + context.getJobDetail().getKey()
                + " executing.[" + new Date() + "]");
        JobDataMap map = context.getJobDetail().getJobDataMap();

        int executeCount = 0;
        if (map.containsKey(NUM_EXECUTIONS)) {
            executeCount = map.getInt(NUM_EXECUTIONS);
        }
        executeCount++;
        map.put(NUM_EXECUTIONS, executeCount);


        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()
                + " complete (" + executeCount + ").");


    }
}

 

MisfireExample

程序首先获取调度程序的一个实例。这是通过创建一个StdSchedulerFactory来完成的,然后使用它来创建一个调度器。这将创建一个简单的基于RAM的调度器,因为没有特定的 quartz.properties配置文件 告诉它执行其他操作。

package com.example06;

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.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * @author :  yulei
 * @data :  2020/5/21 21:30
 * @Version :  1.0
 **/

public class MisfireExample {

    public void run() throws Exception {
        Logger log = LoggerFactory.getLogger(MisfireExample.class);
        log.info("------- Initializing -------------------");
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();
        log.info("------- Initialization Complete -----------");

        Date startTime = nextGivenSecondDate(null, 15);

        //statefulJob1 3秒钟执行一次 (但是会延迟10秒)
        JobDetail job = newJob(StatefulDumbJob.class).withIdentity("statefulJob1", "group1")
                .usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();

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


        // statefulJob2每三秒钟运行一次
        //(但是它会延迟10秒—因此在几次迭代之后故意失火)
        job = newJob(StatefulDumbJob.class).withIdentity("statefulJob2", "group1")
                .usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();

        trigger = newTrigger()
                .withIdentity("trigger2", "group1")
                .startAt(startTime)
                .withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()
                        .withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instructions
                .build();

        ft = sched.scheduleJob(job, trigger);
        log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
                + trigger.getRepeatInterval() / 1000 + " seconds");

        log.info("------- Starting Scheduler ----------------");
        sched.start();
        log.info("------- Started Complete -----------------");
        try {
            // sleep for ten minutes for triggers to file....
            Thread.sleep(600L * 1000L);
        } 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 {
        MisfireExample example = new MisfireExample();
        example.run();

    }

}

withMisfireHandlingInstructionNowWithExistingCount
——以当前时间为触发频率立即触发执行
——执行至FinalTIme的剩余周期次数
——以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
——调整后的FinalTime会略大于根据starttime计算的到的FinalTime值

 

执行后,运行结果如下:

--group1.statefulJob1 executing.[Thu May 21 22:07:15 CST 2020]
---group1.statefulJob2 executing.[Thu May 21 22:07:15 CST 2020]
  -group1.statefulJob1 complete (1).
  -group1.statefulJob2 complete (1).
---group1.statefulJob2 executing.[Thu May 21 22:07:25 CST 2020]
---group1.statefulJob1 executing.[Thu May 21 22:07:27 CST 2020]
  -group1.statefulJob2 complete (2).
---group1.statefulJob2 executing.[Thu May 21 22:07:35 CST 2020]
  -group1.statefulJob1 complete (2).
---group1.statefulJob1 executing.[Thu May 21 22:07:39 CST 2020]
  -group1.statefulJob2 complete (3).
---group1.statefulJob2 executing.[Thu May 21 22:07:45 CST 2020]
  -group1.statefulJob1 complete (3).
---group1.statefulJob1 executing.[Thu May 21 22:07:51 CST 2020]
  -group1.statefulJob2 complete (4).
---group1.statefulJob2 executing.[Thu May 21 22:07:55 CST 2020]
  -group1.statefulJob1 complete (4).
---group1.statefulJob1 executing.[Thu May 21 22:08:03 CST 2020]
  -group1.statefulJob2 complete (5).
---group1.statefulJob2 executing.[Thu May 21 22:08:05 CST 2020]

可以看到 job2 在延迟10秒之后是立即执行的.   而 job1 还是按照 正常的3秒一次执行,错过上次频率,会在下次触发频率开始执行.

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值