QuartZ misfire 处理机制

546 阅读3分钟

在Quartz框架中,misfire(错误触发)是指当一次触发的触发时间被错误时,该触发如何处理的机制。Quartz提供了几种处理misfire的策略,以便根据具体需求进行配置。

Quartz中的失火处理策略:

  1. MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY(忽略misfire策略) :这是默认的misfire处理策略。当一个触发的触发时间被忽略时,将会被忽略,直到下一个预定的触发时间。

  2. MISFIRE_INSTRUCTION_SMART_POLICY(智能失火策略) :这是一个智能的失火处理策略,它会重新修复错误的触发。具体的行为取决于触发的类型:

    • 对于SimpleTrigger,如果错过了下一个预定的触发时间之前的触发时间,就会被立即触发。
    • 对于CronTrigger,如果错过了下一个预定的触发时间之前的触发时间,就会被立即触发。
    • 对于其他类型的点火,使用默认的失火策略。
  3. MISFIRE_INSTRUCTION_FIRE_ONCE_NOW(立即触发) :当一个触发的触发时间丢失时,就会被立即触发。

  4. MISFIRE_INSTRUCTION_DO_NOTHING(不做任何操作) :当一个触发的触发时间被丢失时,它不会触发,丢失的触发将被忽略。

根据具体的需求选择适合的失火处理策略,并在配置文件中进行设置。

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzMisfireExample {

    public static void main(String[] args) throws SchedulerException {
        // 创建调度器工厂
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

        // 创建JobDetail
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("myJob", "group1")
                .build();

        // 创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 每5秒触发一次
                .build();

        // 将JobDetail和Trigger绑定到调度器上
        scheduler.scheduleJob(jobDetail, trigger);

        // 启动调度器
        scheduler.start();
    }

    public static class MyJob implements Job {
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 在这里编写具体的任务逻辑
            System.out.println("Job executed");
        }
    }
}

创建了一个简单的 Quartz 任务,并使用 Cron 表达式配置触发的触发时间。

  1. 任务调度场景:Quartz常用于任务调度,可以在指定的时间触发任务执行。在任务调度场景下,misfire机制处理可以确保即使在某些情况下错过了任务触发的时间,任务仍然能够得到执行。
  2. 循环环境下的任务调度:如果在循环环境中使用Quartz进行任务调度,可能会遇到多个节点同时竞争调度任务的情况。在这种情况下,misfire处理可以确保任务只在一个节点上执行,避免重复执行。
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzMisfireInLoopExample {

    public static void main(String[] args) throws SchedulerException {
        // 创建调度器工厂
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

        // 创建JobDetail
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("myJob", "group1")
                .build();

        // 创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 每5秒触发一次
                .withMisfireHandlingInstructionNowWithRemainingCount() // 设置misfire处理策略为立即触发,保留剩余的触发次数
                .build();

        // 将JobDetail和Trigger绑定到调度器上
        scheduler.scheduleJob(jobDetail, trigger);

        // 启动调度器
        scheduler.start();
    }

    public static class MyJob implements Job {
        private static int count = 0;

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            count++;
            System.out.println("Job executed, count: " + count);

            if (count >= 5) {
                // 如果达到指定的次数,结束任务调度
                Scheduler scheduler = context.getScheduler();
                try {
                    scheduler.shutdown();
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  1. 长时间运行的任务:对于长时间运行的任务,如果错过了任务的某个触发时间,可能会影响任务的整体执行进度。在这种情况下,misfire处理机制可以保证任务能够在错过触发的时间后续立即执行,以保持任务的整体细节。
  2. 需要精确控制任务触发时间的场景:有些任务需要在非常精确的时间点触发,例如在某个特定的行情开盘时间执行某项操作。在这种情况下,失火处理机制可以确保任务在失败的触发时间后立即执行,以保证任务的准确性。