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.