Quartz_2.2.X学习系列十七:Example 5 - Handling Job Misfires

Sometimes job will not execute when they are supposed to. See how to handle these Misfires

 

说明:

因为类使用禁止并发,所以Trigger设置的是3秒执行一次,但是由于每一个JOB都要等10秒,当下一个3秒,Quartz触发新的任务时会失败,因为上一个Job还没有执行完(还需要7秒后才能执行完)。

@PersistJobDataAfterExecution

@DisallowConcurrentExecution

 

------------------------------------------------------------------------------------------------------------

/*

 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.

 *

 * Licensed under the Apache License, Version 2.0 (the "License"); you may not

 * use this file except in compliance with the License. You may obtain a copy

 * of the License at

 *

 *   http://www.apache.org/licenses/LICENSE-2.0

 *  

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

 * License for the specific language governing permissions and limitations

 * under the License.

 *

 */

 

package org.quartz.examples.example5;

 

import org.quartz.DisallowConcurrentExecution;

import org.quartz.Job;

import org.quartz.JobDataMap;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.quartz.PersistJobDataAfterExecution;

 

import java.util.Date;

 

/**

 * <p>

 * A dumb implementation of Job, for unit testing purposes.

 * </p>

 *

 * @author James House

 */

@PersistJobDataAfterExecution

@DisallowConcurrentExecution

public class StatefulDumbJob implements Job {

 

  /*

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Constants.

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   */

 

  public static final String NUM_EXECUTIONS  = "NumExecutions";

 

  public static final String EXECUTION_DELAY = "ExecutionDelay";

 

  /*

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Constructors.

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   */

 

  public StatefulDumbJob() {

  }

 

  /*

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Interface.

   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   */

 

  /**

   * <p>

   * Called by the <code>{@link org.quartz.Scheduler}</code> when a <code>{@link org.quartz.Trigger}</code> fires that

   * is associated with the <code>Job</code>.

   * </p>

   *

   * @throws JobExecutionException if there is an exception while executing the job.

   */

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

 

  }

 

}

 

------------------------------------------------------------------------------------------------------------

 

------------------------------------------------------------------------------------------------------------

/*

 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.

 *

 * Licensed under the Apache License, Version 2.0 (the "License"); you may not

 * use this file except in compliance with the License. You may obtain a copy

 * of the License at

 *

 *   http://www.apache.org/licenses/LICENSE-2.0

 *  

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

 * License for the specific language governing permissions and limitations

 * under the License.

 *

 */

 

package org.quartz.examples.example5;

 

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;

 

/**

 * Demonstrates the behavior of <code>StatefulJob</code>s, as well as how misfire instructions affect the firings of

 * triggers of <code>StatefulJob</code> s - when the jobs take longer to execute that the frequency of the trigger's

 * repitition.

 * <p>

 * While the example is running, you should note that there are two triggers with identical schedules, firing identical

 * jobs. The triggers "want" to fire every 3 seconds, but the jobs take 10 seconds to execute. Therefore, by the time

 * the jobs complete their execution, the triggers have already "misfired" (unless the scheduler's "misfire threshold"

 * has been set to more than 7 seconds). You should see that one of the jobs has its misfire instruction set to

 * <code>SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>, which causes it to fire

 * immediately, when the misfire is detected. The other trigger uses the default "smart policy" misfire instruction,

 * which causes the trigger to advance to its next fire time (skipping those that it has missed) - so that it does not

 * refire immediately, but rather at the next scheduled time.

 * </p>

 *

 * @author <a href="mailto:[email protected]">Chris Bonham</a>

 */

public class MisfireExample {

 

public void run() throws Exception {

Logger log = LoggerFactory.getLogger(MisfireExample.class);

 

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

 

// First we must get a reference to a scheduler

SchedulerFactory sf = new StdSchedulerFactory();

Scheduler sched = sf.getScheduler();

 

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

 

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

 

// jobs can be scheduled before start() has been called

 

// get a "nice round" time a few seconds in the future...

Date startTime = nextGivenSecondDate(null, 15);

 

// statefulJob1 will run every three seconds

// (but it will delay for ten seconds)

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 will run every three seconds

// (but it will delay for ten seconds - and therefore purposely misfire after a

// few iterations)

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 ----------------");

 

// jobs don't start firing until start() has been called...

sched.start();

 

log.info("------- Started Scheduler -----------------");

 

try {

// sleep for ten minutes for triggers to file....

Thread.sleep(60L * 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();

}

 

}

 

------------------------------------------------------------------------------------------------------------

Executing result:

17:46:04.553 INFO  org.quartz.examples.example5.MisfireExample 58 run - ------- Initializing -------------------

17:46:04.604 INFO  org.quartz.impl.StdSchedulerFactory 1172 instantiate - Using default implementation for ThreadExecutor

17:46:04.607 INFO  org.quartz.simpl.SimpleThreadPool 268 initialize - Job execution threads will use class loader of thread: main

17:46:04.622 INFO  org.quartz.core.SchedulerSignalerImpl 61 <init> - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl

17:46:04.623 INFO  org.quartz.core.QuartzScheduler 240 <init> - Quartz Scheduler v.2.2.3 created.

17:46:04.625 INFO  org.quartz.simpl.RAMJobStore 155 initialize - RAMJobStore initialized.

17:46:04.626 INFO  org.quartz.core.QuartzScheduler 305 initialize - Scheduler meta-data: Quartz Scheduler (v2.2.3) '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.

 

17:46:04.627 INFO  org.quartz.impl.StdSchedulerFactory 1327 instantiate - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'

17:46:04.627 INFO  org.quartz.impl.StdSchedulerFactory 1331 instantiate - Quartz scheduler version: 2.2.3

17:46:04.628 INFO  org.quartz.examples.example5.MisfireExample 64 run - ------- Initialization Complete -----------

17:46:04.628 INFO  org.quartz.examples.example5.MisfireExample 66 run - ------- Scheduling Jobs -----------

17:46:04.636 INFO  org.quartz.examples.example5.MisfireExample 86 run - group1.statefulJob1 will run at: Sun Aug 12 17:46:15 CST 2018 and repeat: -1 times, every 3 seconds

17:46:04.636 INFO  org.quartz.examples.example5.MisfireExample 104 run - group1.statefulJob2 will run at: Sun Aug 12 17:46:15 CST 2018 and repeat: -1 times, every 3 seconds

17:46:04.636 INFO  org.quartz.examples.example5.MisfireExample 107 run - ------- Starting Scheduler ----------------

17:46:04.636 INFO  org.quartz.core.QuartzScheduler 575 start - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.

17:46:04.637 INFO  org.quartz.examples.example5.MisfireExample 112 run - ------- Started Scheduler -----------------

---group1.statefulJob1 executing.[Sun Aug 12 17:46:15 CST 2018]

---group1.statefulJob2 executing.[Sun Aug 12 17:46:15 CST 2018]

  -group1.statefulJob2 complete (1).

  -group1.statefulJob1 complete (1).

---group1.statefulJob1 executing.[Sun Aug 12 17:46:25 CST 2018]

---group1.statefulJob2 executing.[Sun Aug 12 17:46:25 CST 2018]

  -group1.statefulJob2 complete (2).

  -group1.statefulJob1 complete (2).

---group1.statefulJob1 executing.[Sun Aug 12 17:46:35 CST 2018]

---group1.statefulJob2 executing.[Sun Aug 12 17:46:35 CST 2018]

  -group1.statefulJob1 complete (3).

  -group1.statefulJob2 complete (3).

---group1.statefulJob1 executing.[Sun Aug 12 17:46:45 CST 2018]

---group1.statefulJob2 executing.[Sun Aug 12 17:46:45 CST 2018]

  -group1.statefulJob1 complete (4).

---group1.statefulJob1 executing.[Sun Aug 12 17:46:55 CST 2018]

  -group1.statefulJob2 complete (4).

---group1.statefulJob2 executing.[Sun Aug 12 17:46:55 CST 2018]

17:47:04.638 INFO  org.quartz.examples.example5.MisfireExample 121 run - ------- Shutting Down ---------------------

17:47:04.639 INFO  org.quartz.core.QuartzScheduler 694 shutdown - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.

17:47:04.642 INFO  org.quartz.core.QuartzScheduler 613 standby - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.

  -group1.statefulJob1 complete (5).

  -group1.statefulJob2 complete (5).

17:47:05.111 INFO  org.quartz.core.QuartzScheduler 771 shutdown - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.

17:47:05.113 INFO  org.quartz.examples.example5.MisfireExample 125 run - ------- Shutdown Complete -----------------

17:47:05.114 INFO  org.quartz.examples.example5.MisfireExample 128 run - Executed 10 jobs.

猜你喜欢

转载自blog.csdn.net/arnolian/article/details/82556636
今日推荐