org.quartz.core.QuartzScheduler
org.quartz.core.QuartzSchedulerThread
执行逻辑图
代码流程图
源代码[注释版本]
GitLab 地址: https://github.com/BoYiZhang/quartz.git
代码入口: org.quartz.core.QuartzTest
-
-
public
class QuartzTest {
-
-
public static void main(String[] args) throws Exception {
-
SimpleDateFormat sdf =
new SimpleDateFormat(
"yyyy-MM-dd hh:mm:ss");
-
-
SchedulerFactory sf =
new StdSchedulerFactory();
-
Scheduler sched = sf.getScheduler();
-
-
JobDetail job = JobBuilder.newJob(HelloJob.class)
-
.withIdentity(
"job1",
"group1").build();
-
-
org.quartz.Trigger trigger = TriggerBuilder.newTrigger()
-
.withIdentity(
"trigger1",
"group1")
-
.startNow()
-
.withSchedule(
-
CronScheduleBuilder.cronSchedule(
"0/2 * * * * ?")
-
.withMisfireHandlingInstructionFireAndProceed()
-
// .withMisfireHandlingInstructionIgnoreMisfires() # MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 忽略所有的超时状态,按照触发器的策略执行。
-
// .withMisfireHandlingInstructionFireAndProceed() # [默认] MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 立刻执行一次,然后就按照正常的计划执行。
-
// .withMisfireHandlingInstructionDoNothing() # MISFIRE_INSTRUCTION_DO_NOTHING 目前不执行,然后就按照正常的计划执行。
-
)
-
.build();
-
-
HolidayCalendar holidayCalendar =
new HolidayCalendar();
-
-
GregorianCalendar calendar =
new GregorianCalendar(
2020,
2,
23);
// 2017年11月1日
-
holidayCalendar.addExcludedDate(calendar.getTime());
-
-
calendar =
new GregorianCalendar(
2020,
2,
21);
// 2018年11月2日
-
holidayCalendar.addExcludedDate(calendar.getTime());
-
-
-
sched.addCalendar(
"holidays", holidayCalendar,
false,
false);
// 节假日加入schedule调度器
-
-
sched.scheduleJob(job, trigger);
-
-
-
-
sched.start();
-
-
}
-
-
}
-
核心代码
org.quartz.core.QuartzScheduler
-
-
/*
-
* 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.core;
-
-
import java.io.InputStream;
-
import java.lang.management.ManagementFactory;
-
import java.rmi.RemoteException;
-
import java.rmi.registry.LocateRegistry;
-
import java.rmi.registry.Registry;
-
import java.rmi.server.UnicastRemoteObject;
-
import java.text.SimpleDateFormat;
-
import java.util.ArrayList;
-
import java.util.Collection;
-
import java.util.Date;
-
import java.util.HashMap;
-
import java.util.LinkedList;
-
import java.util.List;
-
import java.util.Map;
-
import java.util.Properties;
-
import java.util.Random;
-
import java.util.Set;
-
import java.util.Map.Entry;
-
import java.util.concurrent.atomic.AtomicInteger;
-
-
import javax.management.MBeanServer;
-
import javax.management.ObjectName;
-
-
import org.quartz.Calendar;
-
import org.quartz.InterruptableJob;
-
import org.quartz.Job;
-
import org.quartz.JobDataMap;
-
import org.quartz.JobDetail;
-
import org.quartz.JobExecutionContext;
-
import org.quartz.JobExecutionException;
-
import org.quartz.JobKey;
-
import org.quartz.JobListener;
-
import org.quartz.ListenerManager;
-
import org.quartz.Matcher;
-
import org.quartz.ObjectAlreadyExistsException;
-
import org.quartz.Scheduler;
-
import org.quartz.SchedulerContext;
-
import org.quartz.SchedulerException;
-
import org.quartz.SchedulerListener;
-
import org.quartz.SchedulerMetaData;
-
import org.quartz.Trigger;
-
import
static org.quartz.TriggerBuilder.*;
-
import org.quartz.TriggerKey;
-
import org.quartz.TriggerListener;
-
import org.quartz.UnableToInterruptJobException;
-
import org.quartz.Trigger.CompletedExecutionInstruction;
-
import org.quartz.Trigger.TriggerState;
-
import org.quartz.core.jmx.QuartzSchedulerMBean;
-
import org.quartz.impl.SchedulerRepository;
-
import org.quartz.impl.matchers.GroupMatcher;
-
import org.quartz.listeners.SchedulerListenerSupport;
-
import org.quartz.simpl.PropertySettingJobFactory;
-
import org.quartz.spi.JobFactory;
-
import org.quartz.spi.OperableTrigger;
-
import org.quartz.spi.SchedulerPlugin;
-
import org.quartz.spi.SchedulerSignaler;
-
import org.quartz.spi.ThreadExecutor;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
/**
-
* <p>
-
* This is the heart of Quartz, an indirect implementation of the <code>{@link org.quartz.Scheduler}</code>
-
* interface, containing methods to schedule <code>{@link org.quartz.Job}</code>s,
-
* register <code>{@link org.quartz.JobListener}</code> instances, etc.
-
* </p>
-
*
-
* @see org.quartz.Scheduler
-
* @see org.quartz.core.QuartzSchedulerThread
-
* @see org.quartz.spi.JobStore
-
* @see org.quartz.spi.ThreadPool
-
*
-
* @author James House
-
*/
-
public
class QuartzScheduler implements RemotableQuartzScheduler {
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Constants.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
private
static String VERSION_MAJOR =
"UNKNOWN";
-
private
static String VERSION_MINOR =
"UNKNOWN";
-
private
static String VERSION_ITERATION =
"UNKNOWN";
-
-
static {
-
Properties props =
new Properties();
-
InputStream is =
null;
-
try {
-
is = QuartzScheduler.class.getResourceAsStream(
"quartz-build.properties");
-
if(is !=
null) {
-
props.load(is);
-
String version = props.getProperty(
"version");
-
if (version !=
null) {
-
String[] versionComponents = version.split(
"\\.");
-
VERSION_MAJOR = versionComponents[
0];
-
VERSION_MINOR = versionComponents[
1];
-
if(versionComponents.length >
2)
-
VERSION_ITERATION = versionComponents[
2];
-
else
-
VERSION_ITERATION =
"0";
-
}
else {
-
(LoggerFactory.getLogger(QuartzScheduler.class)).error(
-
"Can't parse Quartz version from quartz-build.properties");
-
}
-
}
-
}
catch (Exception e) {
-
(LoggerFactory.getLogger(QuartzScheduler.class)).error(
-
"Error loading version info from quartz-build.properties.", e);
-
}
finally {
-
if(is !=
null) {
-
try { is.close(); }
catch(Exception ignore) {}
-
}
-
}
-
}
-
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Data members.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
private QuartzSchedulerResources resources;
-
-
private QuartzSchedulerThread schedThread;
-
-
private ThreadGroup threadGroup;
-
-
private SchedulerContext context =
new SchedulerContext();
-
-
private ListenerManager listenerManager =
new ListenerManagerImpl();
-
-
private HashMap<String, JobListener> internalJobListeners =
new HashMap<String, JobListener>(
10);
-
-
private HashMap<String, TriggerListener> internalTriggerListeners =
new HashMap<String, TriggerListener>(
10);
-
-
private ArrayList<SchedulerListener> internalSchedulerListeners =
new ArrayList<SchedulerListener>(
10);
-
-
private JobFactory jobFactory =
new PropertySettingJobFactory();
-
-
ExecutingJobsManager jobMgr =
null;
-
-
ErrorLogger errLogger =
null;
-
-
private SchedulerSignaler signaler;
-
-
private Random random =
new Random();
-
-
private ArrayList<Object> holdToPreventGC =
new ArrayList<Object>(
5);
-
-
private
boolean signalOnSchedulingChange =
true;
-
-
private
volatile
boolean closed =
false;
-
private
volatile
boolean shuttingDown =
false;
-
private
boolean boundRemotely =
false;
-
-
private QuartzSchedulerMBean jmxBean =
null;
-
-
private Date initialStart =
null;
-
-
private
final Logger log = LoggerFactory.getLogger(getClass());
-
-
// private static final Map<String, ManagementServer> MGMT_SVR_BY_BIND = new
-
// HashMap<String, ManagementServer>();
-
// private String registeredManagementServerBind;
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Constructors.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
/**
-
* <p>
-
* Create a <code>QuartzScheduler</code> with the given configuration
-
* properties.
-
* </p>
-
*
-
* @see QuartzSchedulerResources
-
*/
-
public QuartzScheduler(QuartzSchedulerResources resources, long idleWaitTime, @Deprecated long dbRetryInterval)
-
throws SchedulerException {
-
this.resources = resources;
-
if (resources.getJobStore()
instanceof JobListener) {
-
addInternalJobListener((JobListener)resources.getJobStore());
-
}
-
-
this.schedThread =
new QuartzSchedulerThread(
this, resources);
-
ThreadExecutor schedThreadExecutor = resources.getThreadExecutor();
-
schedThreadExecutor.execute(
this.schedThread);
-
if (idleWaitTime >
0) {
-
this.schedThread.setIdleWaitTime(idleWaitTime);
-
}
-
-
jobMgr =
new ExecutingJobsManager();
-
addInternalJobListener(jobMgr);
-
errLogger =
new ErrorLogger();
-
addInternalSchedulerListener(errLogger);
-
-
signaler =
new SchedulerSignalerImpl(
this,
this.schedThread);
-
-
getLog().info(
"Quartz Scheduler v." + getVersion() +
" created.");
-
}
-
-
public void initialize() throws SchedulerException {
-
-
try {
-
bind();
-
}
catch (Exception re) {
-
throw
new SchedulerException(
-
"Unable to bind scheduler to RMI Registry.", re);
-
}
-
-
if (resources.getJMXExport()) {
-
try {
-
registerJMX();
-
}
catch (Exception e) {
-
throw
new SchedulerException(
-
"Unable to register scheduler with MBeanServer.", e);
-
}
-
}
-
-
// ManagementRESTServiceConfiguration managementRESTServiceConfiguration
-
// = resources.getManagementRESTServiceConfiguration();
-
//
-
// if (managementRESTServiceConfiguration != null &&
-
// managementRESTServiceConfiguration.isEnabled()) {
-
// try {
-
// /**
-
// * ManagementServer will only be instantiated and started if one
-
// * isn't already running on the configured port for this class
-
// * loader space.
-
// */
-
// synchronized (QuartzScheduler.class) {
-
// if
-
// (!MGMT_SVR_BY_BIND.containsKey(managementRESTServiceConfiguration.getBind()))
-
// {
-
// Class<?> managementServerImplClass =
-
// Class.forName("org.quartz.management.ManagementServerImpl");
-
// Class<?> managementRESTServiceConfigurationClass[] = new Class[] {
-
// managementRESTServiceConfiguration.getClass() };
-
// Constructor<?> managementRESTServiceConfigurationConstructor =
-
// managementServerImplClass
-
// .getConstructor(managementRESTServiceConfigurationClass);
-
// Object arglist[] = new Object[] { managementRESTServiceConfiguration
-
// };
-
// ManagementServer embeddedRESTServer = ((ManagementServer)
-
// managementRESTServiceConfigurationConstructor.newInstance(arglist));
-
// embeddedRESTServer.start();
-
// MGMT_SVR_BY_BIND.put(managementRESTServiceConfiguration.getBind(),
-
// embeddedRESTServer);
-
// }
-
// registeredManagementServerBind =
-
// managementRESTServiceConfiguration.getBind();
-
// ManagementServer embeddedRESTServer =
-
// MGMT_SVR_BY_BIND.get(registeredManagementServerBind);
-
// embeddedRESTServer.register(this);
-
// }
-
// } catch (Exception e) {
-
// throw new
-
// SchedulerException("Unable to start the scheduler management REST service",
-
// e);
-
// }
-
// }
-
-
-
getLog().info(
"Scheduler meta-data: " +
-
(
new SchedulerMetaData(getSchedulerName(),
-
getSchedulerInstanceId(), getClass(), boundRemotely, runningSince() !=
null,
-
isInStandbyMode(), isShutdown(), runningSince(),
-
numJobsExecuted(), getJobStoreClass(),
-
supportsPersistence(), isClustered(), getThreadPoolClass(),
-
getThreadPoolSize(), getVersion())).toString());
-
}
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Interface.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
public String getVersion() {
-
return getVersionMajor() +
"." + getVersionMinor() +
"."
-
+ getVersionIteration();
-
}
-
-
public static String getVersionMajor() {
-
return VERSION_MAJOR;
-
}
-
-
public static String getVersionMinor() {
-
return VERSION_MINOR;
-
}
-
-
public static String getVersionIteration() {
-
return VERSION_ITERATION;
-
}
-
-
public SchedulerSignaler getSchedulerSignaler() {
-
return signaler;
-
}
-
-
public Logger getLog() {
-
return log;
-
}
-
-
/**
-
* Register the scheduler in the local MBeanServer.
-
*/
-
private void registerJMX() throws Exception {
-
String jmxObjectName = resources.getJMXObjectName();
-
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-
jmxBean =
new QuartzSchedulerMBeanImpl(
this);
-
mbs.registerMBean(jmxBean,
new ObjectName(jmxObjectName));
-
}
-
-
/**
-
* Unregister the scheduler from the local MBeanServer.
-
*/
-
private void unregisterJMX() throws Exception {
-
String jmxObjectName = resources.getJMXObjectName();
-
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-
mbs.unregisterMBean(
new ObjectName(jmxObjectName));
-
jmxBean.setSampledStatisticsEnabled(
false);
-
getLog().info(
"Scheduler unregistered from name '" + jmxObjectName +
"' in the local MBeanServer.");
-
}
-
-
/**
-
* <p>
-
* Bind the scheduler to an RMI registry.
-
* </p>
-
*/
-
private void bind() throws RemoteException {
-
String host = resources.getRMIRegistryHost();
-
// don't export if we're not configured to do so...
-
if (host ==
null || host.length() ==
0) {
-
return;
-
}
-
-
RemotableQuartzScheduler exportable =
null;
-
-
if(resources.getRMIServerPort() >
0) {
-
exportable = (RemotableQuartzScheduler) UnicastRemoteObject
-
.exportObject(
this, resources.getRMIServerPort());
-
}
else {
-
exportable = (RemotableQuartzScheduler) UnicastRemoteObject
-
.exportObject(
this);
-
}
-
-
Registry registry =
null;
-
-
if (resources.getRMICreateRegistryStrategy().equals(
-
QuartzSchedulerResources.CREATE_REGISTRY_AS_NEEDED)) {
-
try {
-
// First try to get an existing one, instead of creating it,
-
// since if
-
// we're in a web-app being 'hot' re-depoloyed, then the JVM
-
// still
-
// has the registry that we created above the first time...
-
registry = LocateRegistry.getRegistry(resources
-
.getRMIRegistryPort());
-
registry.list();
-
}
catch (Exception e) {
-
registry = LocateRegistry.createRegistry(resources
-
.getRMIRegistryPort());
-
}
-
}
else
if (resources.getRMICreateRegistryStrategy().equals(
-
QuartzSchedulerResources.CREATE_REGISTRY_ALWAYS)) {
-
try {
-
registry = LocateRegistry.createRegistry(resources
-
.getRMIRegistryPort());
-
}
catch (Exception e) {
-
// Fall back to an existing one, instead of creating it, since
-
// if
-
// we're in a web-app being 'hot' re-depoloyed, then the JVM
-
// still
-
// has the registry that we created above the first time...
-
registry = LocateRegistry.getRegistry(resources
-
.getRMIRegistryPort());
-
}
-
}
else {
-
registry = LocateRegistry.getRegistry(resources
-
.getRMIRegistryHost(), resources.getRMIRegistryPort());
-
}
-
-
String bindName = resources.getRMIBindName();
-
-
registry.rebind(bindName, exportable);
-
-
boundRemotely =
true;
-
-
getLog().info(
"Scheduler bound to RMI registry under name '" + bindName +
"'");
-
}
-
-
/**
-
* <p>
-
* Un-bind the scheduler from an RMI registry.
-
* </p>
-
*/
-
private void unBind() throws RemoteException {
-
String host = resources.getRMIRegistryHost();
-
// don't un-export if we're not configured to do so...
-
if (host ==
null || host.length() ==
0) {
-
return;
-
}
-
-
Registry registry = LocateRegistry.getRegistry(resources
-
.getRMIRegistryHost(), resources.getRMIRegistryPort());
-
-
String bindName = resources.getRMIBindName();
-
-
try {
-
registry.unbind(bindName);
-
UnicastRemoteObject.unexportObject(
this,
true);
-
}
catch (java.rmi.NotBoundException nbe) {
-
}
-
-
getLog().info(
"Scheduler un-bound from name '" + bindName +
"' in RMI registry");
-
}
-
-
/**
-
* <p>
-
* Returns the name of the <code>QuartzScheduler</code>.
-
* </p>
-
*/
-
public String getSchedulerName() {
-
return resources.getName();
-
}
-
-
/**
-
* <p>
-
* Returns the instance Id of the <code>QuartzScheduler</code>.
-
* </p>
-
*/
-
public String getSchedulerInstanceId() {
-
return resources.getInstanceId();
-
}
-
-
/**
-
* <p>
-
* Returns the name of the thread group for Quartz's main threads.
-
* </p>
-
*/
-
public ThreadGroup getSchedulerThreadGroup() {
-
if (threadGroup ==
null) {
-
threadGroup =
new ThreadGroup(
"QuartzScheduler:"
-
+ getSchedulerName());
-
if (resources.getMakeSchedulerThreadDaemon()) {
-
threadGroup.setDaemon(
true);
-
}
-
}
-
-
return threadGroup;
-
}
-
-
public void addNoGCObject(Object obj) {
-
holdToPreventGC.add(obj);
-
}
-
-
public boolean removeNoGCObject(Object obj) {
-
return holdToPreventGC.remove(obj);
-
}
-
-
/**
-
* <p>
-
* Returns the <code>SchedulerContext</code> of the <code>Scheduler</code>.
-
* </p>
-
*/
-
public SchedulerContext getSchedulerContext() throws SchedulerException {
-
return context;
-
}
-
-
public boolean isSignalOnSchedulingChange() {
-
return signalOnSchedulingChange;
-
}
-
-
public void setSignalOnSchedulingChange(boolean signalOnSchedulingChange) {
-
this.signalOnSchedulingChange = signalOnSchedulingChange;
-
}
-
-
///////////////////////////////////////////////////////////////////////////
-
///
-
/// Scheduler State Management Methods
-
///
-
///////////////////////////////////////////////////////////////////////////
-
-
/**
-
* <p>
-
* Starts the <code>QuartzScheduler</code>'s threads that fire <code>{@link org.quartz.Trigger}s</code>.
-
* </p>
-
*
-
* <p>
-
* All <code>{@link org.quartz.Trigger}s</code> that have misfired will
-
* be passed to the appropriate TriggerListener(s).
-
* </p>
-
* todo
-
* 启动的初始化
-
* 判断是否集群,对应不同的操作
-
* 若是非集群,首先有恢复机制,恢复任何失败或misfire的作业,并根据需要清理数据存储。
-
* 初始化线程管理,唤醒所有等待的线程!
-
* 线程中启动线程是调用start()方法,但是真正执行线程任务的操作在run()中!
-
*
-
*/
-
-
public void start() throws SchedulerException {
-
-
if (shuttingDown|| closed) {
-
throw
new SchedulerException(
-
"The Scheduler cannot be restarted after shutdown() has been called.");
-
}
-
-
// QTZ-212 : calling new schedulerStarting() method on the listeners
-
// right after entering start()
-
notifySchedulerListenersStarting();
-
-
//todo 初始化标识为null,进行初始化操作
-
if (initialStart ==
null) {
-
initialStart =
new Date();
-
//todo 1.主要分析的地方
-
this.resources.getJobStore().schedulerStarted();
-
startPlugins();
-
}
else {
-
-
//todo 2.如果已经初始化过,则恢复jobStore
-
resources.getJobStore().schedulerResumed();
-
}
-
//todo 3.唤醒所有等待的线程
-
schedThread.togglePause(
false);
-
-
getLog().info(
-
"Scheduler " + resources.getUniqueIdentifier() +
" started.");
-
-
notifySchedulerListenersStarted();
-
}
-
-
public void startDelayed(final int seconds) throws SchedulerException
-
{
-
if (shuttingDown || closed) {
-
throw
new SchedulerException(
-
"The Scheduler cannot be restarted after shutdown() has been called.");
-
}
-
-
Thread t =
new Thread(
new Runnable() {
-
public void run() {
-
try { Thread.sleep(seconds *
1000L); }
-
catch(InterruptedException ignore) {}
-
try { start(); }
-
catch(SchedulerException se) {
-
getLog().error(
"Unable to start scheduler after startup delay.", se);
-
}
-
}
-
});
-
t.start();
-
}
-
-
/**
-
* <p>
-
* Temporarily halts the <code>QuartzScheduler</code>'s firing of <code>{@link org.quartz.Trigger}s</code>.
-
* </p>
-
*
-
* <p>
-
* The scheduler is not destroyed, and can be re-started at any time.
-
* </p>
-
*/
-
public void standby() {
-
resources.getJobStore().schedulerPaused();
-
schedThread.togglePause(
true);
-
getLog().info(
-
"Scheduler " + resources.getUniqueIdentifier() +
" paused.");
-
notifySchedulerListenersInStandbyMode();
-
}
-
-
/**
-
* <p>
-
* Reports whether the <code>Scheduler</code> is paused.
-
* </p>
-
*/
-
public boolean isInStandbyMode() {
-
return schedThread.isPaused();
-
}
-
-
public Date runningSince() {
-
if(initialStart ==
null)
-
return
null;
-
return
new Date(initialStart.getTime());
-
}
-
-
public int numJobsExecuted() {
-
return jobMgr.getNumJobsFired();
-
}
-
-
public Class<?> getJobStoreClass() {
-
return resources.getJobStore().getClass();
-
}
-
-
public boolean supportsPersistence() {
-
return resources.getJobStore().supportsPersistence();
-
}
-
-
public boolean isClustered() {
-
return resources.getJobStore().isClustered();
-
}
-
-
public Class<?> getThreadPoolClass() {
-
return resources.getThreadPool().getClass();
-
}
-
-
public int getThreadPoolSize() {
-
return resources.getThreadPool().getPoolSize();
-
}
-
-
/**
-
* <p>
-
* Halts the <code>QuartzScheduler</code>'s firing of <code>{@link org.quartz.Trigger}s</code>,
-
* and cleans up all resources associated with the QuartzScheduler.
-
* Equivalent to <code>shutdown(false)</code>.
-
* </p>
-
*
-
* <p>
-
* The scheduler cannot be re-started.
-
* </p>
-
*/
-
public void shutdown() {
-
shutdown(
false);
-
}
-
-
/**
-
* <p>
-
* Halts the <code>QuartzScheduler</code>'s firing of <code>{@link org.quartz.Trigger}s</code>,
-
* and cleans up all resources associated with the QuartzScheduler.
-
* </p>
-
*
-
* <p>
-
* The scheduler cannot be re-started.
-
* </p>
-
*
-
* @param waitForJobsToComplete
-
* if <code>true</code> the scheduler will not allow this method
-
* to return until all currently executing jobs have completed.
-
*/
-
public void shutdown(boolean waitForJobsToComplete) {
-
-
if(shuttingDown || closed) {
-
return;
-
}
-
-
shuttingDown =
true;
-
-
getLog().info(
-
"Scheduler " + resources.getUniqueIdentifier()
-
+
" shutting down.");
-
// boolean removeMgmtSvr = false;
-
// if (registeredManagementServerBind != null) {
-
// ManagementServer standaloneRestServer =
-
// MGMT_SVR_BY_BIND.get(registeredManagementServerBind);
-
//
-
// try {
-
// standaloneRestServer.unregister(this);
-
//
-
// if (!standaloneRestServer.hasRegistered()) {
-
// removeMgmtSvr = true;
-
// standaloneRestServer.stop();
-
// }
-
// } catch (Exception e) {
-
// getLog().warn("Failed to shutdown the ManagementRESTService", e);
-
// } finally {
-
// if (removeMgmtSvr) {
-
// MGMT_SVR_BY_BIND.remove(registeredManagementServerBind);
-
// }
-
//
-
// registeredManagementServerBind = null;
-
// }
-
// }
-
-
standby();
-
-
schedThread.halt(waitForJobsToComplete);
-
-
notifySchedulerListenersShuttingdown();
-
-
if( (resources.isInterruptJobsOnShutdown() && !waitForJobsToComplete) ||
-
(resources.isInterruptJobsOnShutdownWithWait() && waitForJobsToComplete)) {
-
List<JobExecutionContext> jobs = getCurrentlyExecutingJobs();
-
for(JobExecutionContext job: jobs) {
-
if(job.getJobInstance()
instanceof InterruptableJob)
-
try {
-
((InterruptableJob)job.getJobInstance()).interrupt();
-
}
catch (Throwable e) {
-
// do nothing, this was just a courtesy effort
-
getLog().warn(
"Encountered error when interrupting job {} during shutdown: {}", job.getJobDetail().getKey(), e);
-
}
-
}
-
}
-
-
resources.getThreadPool().shutdown(waitForJobsToComplete);
-
-
closed =
true;
-
-
if (resources.getJMXExport()) {
-
try {
-
unregisterJMX();
-
}
catch (Exception e) {
-
}
-
}
-
-
if(boundRemotely) {
-
try {
-
unBind();
-
}
catch (RemoteException re) {
-
}
-
}
-
-
shutdownPlugins();
-
-
resources.getJobStore().shutdown();
-
-
notifySchedulerListenersShutdown();
-
-
SchedulerRepository.getInstance().remove(resources.getName());
-
-
holdToPreventGC.clear();
-
-
getLog().info(
-
"Scheduler " + resources.getUniqueIdentifier()
-
+
" shutdown complete.");
-
}
-
-
/**
-
* <p>
-
* Reports whether the <code>Scheduler</code> has been shutdown.
-
* </p>
-
*/
-
public boolean isShutdown() {
-
return closed;
-
}
-
-
public boolean isShuttingDown() {
-
return shuttingDown;
-
}
-
-
public boolean isStarted() {
-
return !shuttingDown && !closed && !isInStandbyMode() && initialStart !=
null;
-
}
-
-
public void validateState() throws SchedulerException {
-
if (isShutdown()) {
-
throw
new SchedulerException(
"The Scheduler has been shutdown.");
-
}
-
-
// other conditions to check (?)
-
}
-
-
/**
-
* <p>
-
* Return a list of <code>JobExecutionContext</code> objects that
-
* represent all currently executing Jobs in this Scheduler instance.
-
* </p>
-
*
-
* <p>
-
* This method is not cluster aware. That is, it will only return Jobs
-
* currently executing in this Scheduler instance, not across the entire
-
* cluster.
-
* </p>
-
*
-
* <p>
-
* Note that the list returned is an 'instantaneous' snap-shot, and that as
-
* soon as it's returned, the true list of executing jobs may be different.
-
* </p>
-
*/
-
public List<JobExecutionContext> getCurrentlyExecutingJobs() {
-
return jobMgr.getExecutingJobs();
-
}
-
-
///////////////////////////////////////////////////////////////////////////
-
///
-
/// Scheduling-related Methods
-
///
-
///////////////////////////////////////////////////////////////////////////
-
-
/**
-
* <p>
-
* Add the <code>{@link org.quartz.Job}</code> identified by the given
-
* <code>{@link org.quartz.JobDetail}</code> to the Scheduler, and
-
* associate the given <code>{@link org.quartz.Trigger}</code> with it.
-
* </p>
-
*
-
* <p>
-
* If the given Trigger does not reference any <code>Job</code>, then it
-
* will be set to reference the Job passed with it into this method.
-
* </p>
-
*
-
* @throws SchedulerException
-
* if the Job or Trigger cannot be added to the Scheduler, or
-
* there is an internal Scheduler error.
-
*
-
*
-
*
-
-
* 将给定org.quartz.JobDetail标识的org.quartz.Job添加到Scheduler,
-
* 并将给定的org.quartz.Trigger与其关联。
-
* 如果给定的触发器不引用任何作业,则它将被设置为引用与其一起传递的作业到此方法中。
-
*
-
* 实现在 QuartzScheduler.scheduleJob(JobDetail jobDetail,
-
* Trigger trigger)
-
*
-
*/
-
-
-
public Date scheduleJob(JobDetail jobDetail,
-
Trigger trigger)
throws SchedulerException {
-
//todo 验证调度器是否关闭,关闭抛出异常
-
validateState();
-
-
//todo 检查 jobDetail和trigger
-
if (jobDetail ==
null) {
-
throw
new SchedulerException(
"JobDetail cannot be null");
-
}
-
-
if (trigger ==
null) {
-
throw
new SchedulerException(
"Trigger cannot be null");
-
}
-
-
if (jobDetail.getKey() ==
null) {
-
throw
new SchedulerException(
"Job's key cannot be null");
-
}
-
-
if (jobDetail.getJobClass() ==
null) {
-
throw
new SchedulerException(
"Job's class cannot be null");
-
}
-
-
OperableTrigger trig = (OperableTrigger)trigger;
-
-
//todo getJobKey 获取 getJobName(), getJobGroup()
-
if (trigger.getJobKey() ==
null) {
-
trig.setJobKey(jobDetail.getKey());
-
}
else
if (!trigger.getJobKey().equals(jobDetail.getKey())) {
-
throw
new SchedulerException(
-
"Trigger does not reference given job!");
-
}
-
-
//todo 验证trigger
-
trig.validate();
-
-
Calendar cal =
null;
-
if (trigger.getCalendarName() !=
null) {
-
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
-
}
-
-
//todo 在触发器首次添加到调度程序时由调度程序调用,以便让触发器基于任何关联的日历计算
-
//todo 其第一次触发时间。调用此方法后,getNextFireTime()应返回有效的答案。
-
Date ft = trig.computeFirstFireTime(cal);
-
-
if (ft ==
null) {
-
throw
new SchedulerException(
-
"Based on configured schedule, the given trigger '" + trigger.getKey() +
"' will never fire.");
-
}
else{
-
SimpleDateFormat sdf =
new SimpleDateFormat(
"yyyy-MM-dd hh:mm:ss");
-
System.out.println(
"computeFirstFireTime : "+ sdf.format(ft));
-
}
-
-
//todo 存储给定的org.quartz.JobDetail和org.quartz.Trigger。
-
//todo 主要看这一行
-
-
-
//todo org.quartz.impl.jdbcjobstore#JobStoreSupport
-
resources.getJobStore().storeJobAndTrigger(jobDetail, trig);
-
-
-
-
notifySchedulerListenersJobAdded(jobDetail);
-
notifySchedulerThread(trigger.getNextFireTime().getTime());
-
notifySchedulerListenersSchduled(trigger);
-
-
return ft;
-
}
-
-
/**
-
* <p>
-
* Schedule the given <code>{@link org.quartz.Trigger}</code> with the
-
* <code>Job</code> identified by the <code>Trigger</code>'s settings.
-
* </p>
-
*
-
* @throws SchedulerException
-
* if the indicated Job does not exist, or the Trigger cannot be
-
* added to the Scheduler, or there is an internal Scheduler
-
* error.
-
*/
-
public Date scheduleJob(Trigger trigger)
-
throws SchedulerException {
-
validateState();
-
-
if (trigger ==
null) {
-
throw
new SchedulerException(
"Trigger cannot be null");
-
}
-
-
OperableTrigger trig = (OperableTrigger)trigger;
-
-
trig.validate();
-
-
Calendar cal =
null;
-
if (trigger.getCalendarName() !=
null) {
-
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
-
if(cal ==
null) {
-
throw
new SchedulerException(
-
"Calendar not found: " + trigger.getCalendarName());
-
}
-
}
-
Date ft = trig.computeFirstFireTime(cal);
-
-
if (ft ==
null) {
-
throw
new SchedulerException(
-
"Based on configured schedule, the given trigger '" + trigger.getKey() +
"' will never fire.");
-
}
-
-
resources.getJobStore().storeTrigger(trig,
false);
-
notifySchedulerThread(trigger.getNextFireTime().getTime());
-
notifySchedulerListenersSchduled(trigger);
-
-
return ft;
-
}
-
-
/**
-
* <p>
-
* Add the given <code>Job</code> to the Scheduler - with no associated
-
* <code>Trigger</code>. The <code>Job</code> will be 'dormant' until
-
* it is scheduled with a <code>Trigger</code>, or <code>Scheduler.triggerJob()</code>
-
* is called for it.
-
* </p>
-
*
-
* <p>
-
* The <code>Job</code> must by definition be 'durable', if it is not,
-
* SchedulerException will be thrown.
-
* </p>
-
*
-
* @throws SchedulerException
-
* if there is an internal Scheduler error, or if the Job is not
-
* durable, or a Job with the same name already exists, and
-
* <code>replace</code> is <code>false</code>.
-
*/
-
public void addJob(JobDetail jobDetail, boolean replace) throws SchedulerException {
-
addJob(jobDetail, replace,
false);
-
}
-
-
public void addJob(JobDetail jobDetail, boolean replace, boolean storeNonDurableWhileAwaitingScheduling) throws SchedulerException {
-
validateState();
-
-
if (!storeNonDurableWhileAwaitingScheduling && !jobDetail.isDurable()) {
-
throw
new SchedulerException(
-
"Jobs added with no trigger must be durable.");
-
}
-
-
resources.getJobStore().storeJob(jobDetail, replace);
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersJobAdded(jobDetail);
-
}
-
-
/**
-
* <p>
-
* Delete the identified <code>Job</code> from the Scheduler - and any
-
* associated <code>Trigger</code>s.
-
* </p>
-
*
-
* @return true if the Job was found and deleted.
-
* @throws SchedulerException
-
* if there is an internal Scheduler error.
-
*/
-
public boolean deleteJob(JobKey jobKey) throws SchedulerException {
-
validateState();
-
-
boolean result =
false;
-
-
List<? extends Trigger> triggers = getTriggersOfJob(jobKey);
-
for (Trigger trigger : triggers) {
-
if (!unscheduleJob(trigger.getKey())) {
-
StringBuilder sb =
new StringBuilder().append(
-
"Unable to unschedule trigger [").append(
-
trigger.getKey()).append(
"] while deleting job [")
-
.append(jobKey).append(
-
"]");
-
throw
new SchedulerException(sb.toString());
-
}
-
result =
true;
-
}
-
-
result = resources.getJobStore().removeJob(jobKey) || result;
-
if (result) {
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersJobDeleted(jobKey);
-
}
-
return result;
-
}
-
-
public boolean deleteJobs(List<JobKey> jobKeys) throws SchedulerException {
-
validateState();
-
-
boolean result =
false;
-
-
result = resources.getJobStore().removeJobs(jobKeys);
-
notifySchedulerThread(
0L);
-
for(JobKey key: jobKeys)
-
notifySchedulerListenersJobDeleted(key);
-
return result;
-
}
-
-
public void scheduleJobs(Map<JobDetail, Set<? extends Trigger>> triggersAndJobs, boolean replace) throws SchedulerException {
-
validateState();
-
-
// make sure all triggers refer to their associated job
-
for(Entry<JobDetail, Set<? extends Trigger>> e: triggersAndJobs.entrySet()) {
-
JobDetail job = e.getKey();
-
if(job ==
null)
// there can be one of these (for adding a bulk set of triggers for pre-existing jobs)
-
continue;
-
Set<? extends Trigger> triggers = e.getValue();
-
if(triggers ==
null)
// this is possible because the job may be durable, and not yet be having triggers
-
continue;
-
for(Trigger trigger: triggers) {
-
OperableTrigger opt = (OperableTrigger)trigger;
-
opt.setJobKey(job.getKey());
-
-
opt.validate();
-
-
Calendar cal =
null;
-
if (trigger.getCalendarName() !=
null) {
-
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
-
if(cal ==
null) {
-
throw
new SchedulerException(
-
"Calendar '" + trigger.getCalendarName() +
"' not found for trigger: " + trigger.getKey());
-
}
-
}
-
Date ft = opt.computeFirstFireTime(cal);
-
-
if (ft ==
null) {
-
throw
new SchedulerException(
-
"Based on configured schedule, the given trigger will never fire.");
-
}
-
}
-
}
-
-
resources.getJobStore().storeJobsAndTriggers(triggersAndJobs, replace);
-
notifySchedulerThread(
0L);
-
for (JobDetail job : triggersAndJobs.keySet()) {
-
notifySchedulerListenersJobAdded(job);
-
-
Set<? extends Trigger> triggers = triggersAndJobs.get(job);
-
for (Trigger trigger : triggers) {
-
notifySchedulerListenersSchduled(trigger);
-
}
-
}
-
}
-
-
public void scheduleJob(JobDetail jobDetail, Set<? extends Trigger> triggersForJob,
-
boolean replace)
throws SchedulerException {
-
Map<JobDetail, Set<? extends Trigger>> triggersAndJobs =
new HashMap<JobDetail, Set<? extends Trigger>>();
-
triggersAndJobs.put(jobDetail, triggersForJob);
-
scheduleJobs(triggersAndJobs, replace);
-
}
-
-
public boolean unscheduleJobs(List<TriggerKey> triggerKeys) throws SchedulerException {
-
validateState();
-
-
boolean result =
false;
-
-
result = resources.getJobStore().removeTriggers(triggerKeys);
-
notifySchedulerThread(
0L);
-
for(TriggerKey key: triggerKeys)
-
notifySchedulerListenersUnscheduled(key);
-
return result;
-
}
-
-
/**
-
* <p>
-
* Remove the indicated <code>{@link org.quartz.Trigger}</code> from the
-
* scheduler.
-
* </p>
-
*/
-
public boolean unscheduleJob(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
if (resources.getJobStore().removeTrigger(triggerKey)) {
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersUnscheduled(triggerKey);
-
}
else {
-
return
false;
-
}
-
-
return
true;
-
}
-
-
-
/**
-
* <p>
-
* Remove (delete) the <code>{@link org.quartz.Trigger}</code> with the
-
* given name, and store the new given one - which must be associated
-
* with the same job.
-
* </p>
-
* @param newTrigger
-
* The new <code>Trigger</code> to be stored.
-
*
-
* @return <code>null</code> if a <code>Trigger</code> with the given
-
* name & group was not found and removed from the store, otherwise
-
* the first fire time of the newly scheduled trigger.
-
*/
-
public Date rescheduleJob(TriggerKey triggerKey,
-
Trigger newTrigger)
throws SchedulerException {
-
validateState();
-
-
if (triggerKey ==
null) {
-
throw
new IllegalArgumentException(
"triggerKey cannot be null");
-
}
-
if (newTrigger ==
null) {
-
throw
new IllegalArgumentException(
"newTrigger cannot be null");
-
}
-
-
OperableTrigger trig = (OperableTrigger)newTrigger;
-
Trigger oldTrigger = getTrigger(triggerKey);
-
if (oldTrigger ==
null) {
-
return
null;
-
}
else {
-
trig.setJobKey(oldTrigger.getJobKey());
-
}
-
trig.validate();
-
-
Calendar cal =
null;
-
if (newTrigger.getCalendarName() !=
null) {
-
cal = resources.getJobStore().retrieveCalendar(
-
newTrigger.getCalendarName());
-
}
-
Date ft = trig.computeFirstFireTime(cal);
-
-
if (ft ==
null) {
-
throw
new SchedulerException(
-
"Based on configured schedule, the given trigger will never fire.");
-
}
-
-
if (resources.getJobStore().replaceTrigger(triggerKey, trig)) {
-
notifySchedulerThread(newTrigger.getNextFireTime().getTime());
-
notifySchedulerListenersUnscheduled(triggerKey);
-
notifySchedulerListenersSchduled(newTrigger);
-
}
else {
-
return
null;
-
}
-
-
return ft;
-
-
}
-
-
-
private String newTriggerId() {
-
long r = random.nextLong();
-
if (r <
0) {
-
r = -r;
-
}
-
return
"MT_"
-
+ Long.toString(r,
30 + (
int) (System.currentTimeMillis() %
7));
-
}
-
-
/**
-
* <p>
-
* Trigger the identified <code>{@link org.quartz.Job}</code> (execute it
-
* now) - with a non-volatile trigger.
-
* </p>
-
*/
-
@SuppressWarnings(
"deprecation")
-
public void triggerJob(JobKey jobKey, JobDataMap data) throws SchedulerException {
-
validateState();
-
-
OperableTrigger trig = (OperableTrigger) newTrigger().withIdentity(newTriggerId(), Scheduler.DEFAULT_GROUP).forJob(jobKey).build();
-
trig.computeFirstFireTime(
null);
-
if(data !=
null) {
-
trig.setJobDataMap(data);
-
}
-
-
boolean collision =
true;
-
while (collision) {
-
try {
-
resources.getJobStore().storeTrigger(trig,
false);
-
collision =
false;
-
}
catch (ObjectAlreadyExistsException oaee) {
-
trig.setKey(
new TriggerKey(newTriggerId(), Scheduler.DEFAULT_GROUP));
-
}
-
}
-
-
notifySchedulerThread(trig.getNextFireTime().getTime());
-
notifySchedulerListenersSchduled(trig);
-
}
-
-
/**
-
* <p>
-
* Store and schedule the identified <code>{@link org.quartz.spi.OperableTrigger}</code>
-
* </p>
-
*/
-
public void triggerJob(OperableTrigger trig) throws SchedulerException {
-
validateState();
-
-
trig.computeFirstFireTime(
null);
-
-
boolean collision =
true;
-
while (collision) {
-
try {
-
resources.getJobStore().storeTrigger(trig,
false);
-
collision =
false;
-
}
catch (ObjectAlreadyExistsException oaee) {
-
trig.setKey(
new TriggerKey(newTriggerId(), Scheduler.DEFAULT_GROUP));
-
}
-
}
-
-
notifySchedulerThread(trig.getNextFireTime().getTime());
-
notifySchedulerListenersSchduled(trig);
-
}
-
-
/**
-
* <p>
-
* Pause the <code>{@link Trigger}</code> with the given name.
-
* </p>
-
*
-
*/
-
public void pauseTrigger(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().pauseTrigger(triggerKey);
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersPausedTrigger(triggerKey);
-
}
-
-
/**
-
* <p>
-
* Pause all of the <code>{@link Trigger}s</code> in the matching groups.
-
* </p>
-
*
-
*/
-
public void pauseTriggers(GroupMatcher<TriggerKey> matcher)
-
throws SchedulerException {
-
validateState();
-
-
if(matcher ==
null) {
-
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
Collection<String> pausedGroups = resources.getJobStore().pauseTriggers(matcher);
-
notifySchedulerThread(
0L);
-
for (String pausedGroup : pausedGroups) {
-
notifySchedulerListenersPausedTriggers(pausedGroup);
-
}
-
}
-
-
/**
-
* <p>
-
* Pause the <code>{@link org.quartz.JobDetail}</code> with the given
-
* name - by pausing all of its current <code>Trigger</code>s.
-
* </p>
-
*
-
*/
-
public void pauseJob(JobKey jobKey) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().pauseJob(jobKey);
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersPausedJob(jobKey);
-
}
-
-
/**
-
* <p>
-
* Pause all of the <code>{@link org.quartz.JobDetail}s</code> in the
-
* matching groups - by pausing all of their <code>Trigger</code>s.
-
* </p>
-
*
-
*/
-
public void pauseJobs(GroupMatcher<JobKey> groupMatcher)
-
throws SchedulerException {
-
validateState();
-
-
if(groupMatcher ==
null) {
-
groupMatcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
Collection<String> pausedGroups = resources.getJobStore().pauseJobs(groupMatcher);
-
notifySchedulerThread(
0L);
-
for (String pausedGroup : pausedGroups) {
-
notifySchedulerListenersPausedJobs(pausedGroup);
-
}
-
}
-
-
/**
-
* <p>
-
* Resume (un-pause) the <code>{@link Trigger}</code> with the given
-
* name.
-
* </p>
-
*
-
* <p>
-
* If the <code>Trigger</code> missed one or more fire-times, then the
-
* <code>Trigger</code>'s misfire instruction will be applied.
-
* </p>
-
*
-
*/
-
public void resumeTrigger(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().resumeTrigger(triggerKey);
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersResumedTrigger(triggerKey);
-
}
-
-
/**
-
* <p>
-
* Resume (un-pause) all of the <code>{@link Trigger}s</code> in the
-
* matching groups.
-
* </p>
-
*
-
* <p>
-
* If any <code>Trigger</code> missed one or more fire-times, then the
-
* <code>Trigger</code>'s misfire instruction will be applied.
-
* </p>
-
*
-
*/
-
public void resumeTriggers(GroupMatcher<TriggerKey> matcher)
-
throws SchedulerException {
-
validateState();
-
-
if(matcher ==
null) {
-
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
Collection<String> pausedGroups = resources.getJobStore().resumeTriggers(matcher);
-
notifySchedulerThread(
0L);
-
for (String pausedGroup : pausedGroups) {
-
notifySchedulerListenersResumedTriggers(pausedGroup);
-
}
-
}
-
-
public Set<String> getPausedTriggerGroups() throws SchedulerException {
-
return resources.getJobStore().getPausedTriggerGroups();
-
}
-
-
/**
-
* <p>
-
* Resume (un-pause) the <code>{@link org.quartz.JobDetail}</code> with
-
* the given name.
-
* </p>
-
*
-
* <p>
-
* If any of the <code>Job</code>'s<code>Trigger</code> s missed one
-
* or more fire-times, then the <code>Trigger</code>'s misfire
-
* instruction will be applied.
-
* </p>
-
*
-
*/
-
public void resumeJob(JobKey jobKey) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().resumeJob(jobKey);
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersResumedJob(jobKey);
-
}
-
-
/**
-
* <p>
-
* Resume (un-pause) all of the <code>{@link org.quartz.JobDetail}s</code>
-
* in the matching groups.
-
* </p>
-
*
-
* <p>
-
* If any of the <code>Job</code> s had <code>Trigger</code> s that
-
* missed one or more fire-times, then the <code>Trigger</code>'s
-
* misfire instruction will be applied.
-
* </p>
-
*
-
*/
-
public void resumeJobs(GroupMatcher<JobKey> matcher)
-
throws SchedulerException {
-
validateState();
-
-
if(matcher ==
null) {
-
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
Collection<String> resumedGroups = resources.getJobStore().resumeJobs(matcher);
-
notifySchedulerThread(
0L);
-
for (String pausedGroup : resumedGroups) {
-
notifySchedulerListenersResumedJobs(pausedGroup);
-
}
-
}
-
-
/**
-
* <p>
-
* Pause all triggers - equivalent of calling <code>pauseTriggers(GroupMatcher<TriggerKey>)</code>
-
* with a matcher matching all known groups.
-
* </p>
-
*
-
* <p>
-
* When <code>resumeAll()</code> is called (to un-pause), trigger misfire
-
* instructions WILL be applied.
-
* </p>
-
*
-
* @see #resumeAll()
-
* @see #pauseTriggers(org.quartz.impl.matchers.GroupMatcher)
-
* @see #standby()
-
*/
-
public void pauseAll() throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().pauseAll();
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersPausedTriggers(
null);
-
}
-
-
/**
-
* <p>
-
* Resume (un-pause) all triggers - equivalent of calling <code>resumeTriggerGroup(group)</code>
-
* on every group.
-
* </p>
-
*
-
* <p>
-
* If any <code>Trigger</code> missed one or more fire-times, then the
-
* <code>Trigger</code>'s misfire instruction will be applied.
-
* </p>
-
*
-
* @see #pauseAll()
-
*/
-
public void resumeAll() throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().resumeAll();
-
notifySchedulerThread(
0L);
-
notifySchedulerListenersResumedTrigger(
null);
-
}
-
-
/**
-
* <p>
-
* Get the names of all known <code>{@link org.quartz.Job}</code> groups.
-
* </p>
-
*/
-
public List<String> getJobGroupNames()
-
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().getJobGroupNames();
-
}
-
-
/**
-
* <p>
-
* Get the names of all the <code>{@link org.quartz.Job}s</code> in the
-
* matching groups.
-
* </p>
-
*/
-
public Set<JobKey> getJobKeys(GroupMatcher<JobKey> matcher)
-
throws SchedulerException {
-
validateState();
-
-
if(matcher ==
null) {
-
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
return resources.getJobStore().getJobKeys(matcher);
-
}
-
-
/**
-
* <p>
-
* Get all <code>{@link Trigger}</code> s that are associated with the
-
* identified <code>{@link org.quartz.JobDetail}</code>.
-
* </p>
-
*/
-
public List<? extends Trigger> getTriggersOfJob(JobKey jobKey)
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().getTriggersForJob(jobKey);
-
}
-
-
/**
-
* <p>
-
* Get the names of all known <code>{@link org.quartz.Trigger}</code>
-
* groups.
-
* </p>
-
*/
-
public List<String> getTriggerGroupNames()
-
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().getTriggerGroupNames();
-
}
-
-
/**
-
* <p>
-
* Get the names of all the <code>{@link org.quartz.Trigger}s</code> in
-
* the matching groups.
-
* </p>
-
*/
-
public Set<TriggerKey> getTriggerKeys(GroupMatcher<TriggerKey> matcher)
-
throws SchedulerException {
-
validateState();
-
-
if(matcher ==
null) {
-
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
-
}
-
-
return resources.getJobStore().getTriggerKeys(matcher);
-
}
-
-
/**
-
* <p>
-
* Get the <code>{@link JobDetail}</code> for the <code>Job</code>
-
* instance with the given name and group.
-
* </p>
-
*/
-
public JobDetail getJobDetail(JobKey jobKey) throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().retrieveJob(jobKey);
-
}
-
-
/**
-
* <p>
-
* Get the <code>{@link Trigger}</code> instance with the given name and
-
* group.
-
* </p>
-
*/
-
public Trigger getTrigger(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().retrieveTrigger(triggerKey);
-
}
-
-
/**
-
* Determine whether a {@link Job} with the given identifier already
-
* exists within the scheduler.
-
*
-
* @param jobKey the identifier to check for
-
* @return true if a Job exists with the given identifier
-
* @throws SchedulerException
-
*/
-
public boolean checkExists(JobKey jobKey) throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().checkExists(jobKey);
-
-
}
-
-
/**
-
* Determine whether a {@link Trigger} with the given identifier already
-
* exists within the scheduler.
-
*
-
* @param triggerKey the identifier to check for
-
* @return true if a Trigger exists with the given identifier
-
* @throws SchedulerException
-
*/
-
public boolean checkExists(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().checkExists(triggerKey);
-
-
}
-
-
/**
-
* Clears (deletes!) all scheduling data - all {@link Job}s, {@link Trigger}s
-
* {@link Calendar}s.
-
*
-
* @throws SchedulerException
-
*/
-
public void clear() throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().clearAllSchedulingData();
-
notifySchedulerListenersUnscheduled(
null);
-
}
-
-
-
/**
-
* <p>
-
* Get the current state of the identified <code>{@link Trigger}</code>.
-
* </p>
-
J *
-
* @see TriggerState
-
*/
-
public TriggerState getTriggerState(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().getTriggerState(triggerKey);
-
}
-
-
-
public void resetTriggerFromErrorState(TriggerKey triggerKey) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().resetTriggerFromErrorState(triggerKey);
-
}
-
-
/**
-
* <p>
-
* Add (register) the given <code>Calendar</code> to the Scheduler.
-
* </p>
-
*
-
* @throws SchedulerException
-
* if there is an internal Scheduler error, or a Calendar with
-
* the same name already exists, and <code>replace</code> is
-
* <code>false</code>.
-
*/
-
public void addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers) throws SchedulerException {
-
validateState();
-
-
resources.getJobStore().storeCalendar(calName, calendar, replace, updateTriggers);
-
}
-
-
/**
-
* <p>
-
* Delete the identified <code>Calendar</code> from the Scheduler.
-
* </p>
-
*
-
* @return true if the Calendar was found and deleted.
-
* @throws SchedulerException
-
* if there is an internal Scheduler error.
-
*/
-
public boolean deleteCalendar(String calName)
-
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().removeCalendar(calName);
-
}
-
-
/**
-
* <p>
-
* Get the <code>{@link Calendar}</code> instance with the given name.
-
* </p>
-
*/
-
public Calendar getCalendar(String calName)
-
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().retrieveCalendar(calName);
-
}
-
-
/**
-
* <p>
-
* Get the names of all registered <code>{@link Calendar}s</code>.
-
* </p>
-
*/
-
public List<String> getCalendarNames()
-
throws SchedulerException {
-
validateState();
-
-
return resources.getJobStore().getCalendarNames();
-
}
-
-
public ListenerManager getListenerManager() {
-
return listenerManager;
-
}
-
-
/**
-
* <p>
-
* Add the given <code>{@link org.quartz.JobListener}</code> to the
-
* <code>Scheduler</code>'s <i>internal</i> list.
-
* </p>
-
*/
-
public void addInternalJobListener(JobListener jobListener) {
-
if (jobListener.getName() ==
null
-
|| jobListener.getName().length() ==
0) {
-
throw
new IllegalArgumentException(
-
"JobListener name cannot be empty.");
-
}
-
-
synchronized (internalJobListeners) {
-
internalJobListeners.put(jobListener.getName(), jobListener);
-
}
-
}
-
-
/**
-
* <p>
-
* Remove the identified <code>{@link JobListener}</code> from the <code>Scheduler</code>'s
-
* list of <i>internal</i> listeners.
-
* </p>
-
*
-
* @return true if the identified listener was found in the list, and
-
* removed.
-
*/
-
public boolean removeInternalJobListener(String name) {
-
synchronized (internalJobListeners) {
-
return (internalJobListeners.remove(name) !=
null);
-
}
-
}
-
-
/**
-
* <p>
-
* Get a List containing all of the <code>{@link org.quartz.JobListener}</code>s
-
* in the <code>Scheduler</code>'s <i>internal</i> list.
-
* </p>
-
*/
-
public List<JobListener> getInternalJobListeners() {
-
synchronized (internalJobListeners) {
-
return java.util.Collections.unmodifiableList(
new LinkedList<JobListener>(internalJobListeners.values()));
-
}
-
}
-
-
/**
-
* <p>
-
* Get the <i>internal</i> <code>{@link org.quartz.JobListener}</code>
-
* that has the given name.
-
* </p>
-
*/
-
public JobListener getInternalJobListener(String name) {
-
synchronized (internalJobListeners) {
-
return internalJobListeners.get(name);
-
}
-
}
-
-
/**
-
* <p>
-
* Add the given <code>{@link org.quartz.TriggerListener}</code> to the
-
* <code>Scheduler</code>'s <i>internal</i> list.
-
* </p>
-
*/
-
public void addInternalTriggerListener(TriggerListener triggerListener) {
-
if (triggerListener.getName() ==
null
-
|| triggerListener.getName().length() ==
0) {
-
throw
new IllegalArgumentException(
-
"TriggerListener name cannot be empty.");
-
}
-
-
synchronized (internalTriggerListeners) {
-
internalTriggerListeners.put(triggerListener.getName(), triggerListener);
-
}
-
}
-
-
/**
-
* <p>
-
* Remove the identified <code>{@link TriggerListener}</code> from the <code>Scheduler</code>'s
-
* list of <i>internal</i> listeners.
-
* </p>
-
*
-
* @return true if the identified listener was found in the list, and
-
* removed.
-
*/
-
public boolean removeinternalTriggerListener(String name) {
-
synchronized (internalTriggerListeners) {
-
return (internalTriggerListeners.remove(name) !=
null);
-
}
-
}
-
-
/**
-
* <p>
-
* Get a list containing all of the <code>{@link org.quartz.TriggerListener}</code>s
-
* in the <code>Scheduler</code>'s <i>internal</i> list.
-
* </p>
-
*/
-
public List<TriggerListener> getInternalTriggerListeners() {
-
synchronized (internalTriggerListeners) {
-
return java.util.Collections.unmodifiableList(
new LinkedList<TriggerListener>(internalTriggerListeners.values()));
-
}
-
}
-
-
/**
-
* <p>
-
* Get the <i>internal</i> <code>{@link TriggerListener}</code> that
-
* has the given name.
-
* </p>
-
*/
-
public TriggerListener getInternalTriggerListener(String name) {
-
synchronized (internalTriggerListeners) {
-
return internalTriggerListeners.get(name);
-
}
-
}
-
-
/**
-
* <p>
-
* Register the given <code>{@link SchedulerListener}</code> with the
-
* <code>Scheduler</code>'s list of internal listeners.
-
* </p>
-
*/
-
public void addInternalSchedulerListener(SchedulerListener schedulerListener) {
-
synchronized (internalSchedulerListeners) {
-
internalSchedulerListeners.add(schedulerListener);
-
}
-
}
-
-
/**
-
* <p>
-
* Remove the given <code>{@link SchedulerListener}</code> from the
-
* <code>Scheduler</code>'s list of internal listeners.
-
* </p>
-
*
-
* @return true if the identified listener was found in the list, and
-
* removed.
-
*/
-
public boolean removeInternalSchedulerListener(SchedulerListener schedulerListener) {
-
synchronized (internalSchedulerListeners) {
-
return internalSchedulerListeners.remove(schedulerListener);
-
}
-
}
-
-
/**
-
* <p>
-
* Get a List containing all of the <i>internal</i> <code>{@link SchedulerListener}</code>s
-
* registered with the <code>Scheduler</code>.
-
* </p>
-
*/
-
public List<SchedulerListener> getInternalSchedulerListeners() {
-
synchronized (internalSchedulerListeners) {
-
return java.util.Collections.unmodifiableList(
new ArrayList<SchedulerListener>(internalSchedulerListeners));
-
}
-
}
-
-
protected void notifyJobStoreJobComplete(OperableTrigger trigger, JobDetail detail, CompletedExecutionInstruction instCode) {
-
resources.getJobStore().triggeredJobComplete(trigger, detail, instCode);
-
}
-
-
protected void notifyJobStoreJobVetoed(OperableTrigger trigger, JobDetail detail, CompletedExecutionInstruction instCode) {
-
resources.getJobStore().triggeredJobComplete(trigger, detail, instCode);
-
}
-
-
protected void notifySchedulerThread(long candidateNewNextFireTime) {
-
if (isSignalOnSchedulingChange()) {
-
signaler.signalSchedulingChange(candidateNewNextFireTime);
-
}
-
}
-
-
private List<TriggerListener> buildTriggerListenerList()
-
throws SchedulerException {
-
List<TriggerListener> allListeners =
new LinkedList<TriggerListener>();
-
allListeners.addAll(getListenerManager().getTriggerListeners());
-
allListeners.addAll(getInternalTriggerListeners());
-
-
return allListeners;
-
}
-
-
private List<JobListener> buildJobListenerList()
-
throws SchedulerException {
-
List<JobListener> allListeners =
new LinkedList<JobListener>();
-
allListeners.addAll(getListenerManager().getJobListeners());
-
allListeners.addAll(getInternalJobListeners());
-
-
return allListeners;
-
}
-
-
private List<SchedulerListener> buildSchedulerListenerList() {
-
List<SchedulerListener> allListeners =
new LinkedList<SchedulerListener>();
-
allListeners.addAll(getListenerManager().getSchedulerListeners());
-
allListeners.addAll(getInternalSchedulerListeners());
-
-
return allListeners;
-
}
-
-
private boolean matchJobListener(JobListener listener, JobKey key) {
-
List<Matcher<JobKey>> matchers = getListenerManager().getJobListenerMatchers(listener.getName());
-
if(matchers ==
null)
-
return
true;
-
for(Matcher<JobKey> matcher: matchers) {
-
if(matcher.isMatch(key))
-
return
true;
-
}
-
return
false;
-
}
-
-
private boolean matchTriggerListener(TriggerListener listener, TriggerKey key) {
-
List<Matcher<TriggerKey>> matchers = getListenerManager().getTriggerListenerMatchers(listener.getName());
-
if(matchers ==
null)
-
return
true;
-
for(Matcher<TriggerKey> matcher: matchers) {
-
if(matcher.isMatch(key))
-
return
true;
-
}
-
return
false;
-
}
-
-
public boolean notifyTriggerListenersFired(JobExecutionContext jec)
-
throws SchedulerException {
-
-
boolean vetoedExecution =
false;
-
-
// build a list of all trigger listeners that are to be notified...
-
List<TriggerListener> triggerListeners = buildTriggerListenerList();
-
-
// notify all trigger listeners in the list
-
for(TriggerListener tl: triggerListeners) {
-
try {
-
if(!matchTriggerListener(tl, jec.getTrigger().getKey()))
-
continue;
-
tl.triggerFired(jec.getTrigger(), jec);
-
-
if(tl.vetoJobExecution(jec.getTrigger(), jec)) {
-
vetoedExecution =
true;
-
}
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"TriggerListener '" + tl.getName()
-
+
"' threw exception: " + e.getMessage(), e);
-
throw se;
-
}
-
}
-
-
return vetoedExecution;
-
}
-
-
-
public void notifyTriggerListenersMisfired(Trigger trigger)
-
throws SchedulerException {
-
// build a list of all trigger listeners that are to be notified...
-
List<TriggerListener> triggerListeners = buildTriggerListenerList();
-
-
// notify all trigger listeners in the list
-
for(TriggerListener tl: triggerListeners) {
-
try {
-
if(!matchTriggerListener(tl, trigger.getKey()))
-
continue;
-
tl.triggerMisfired(trigger);
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"TriggerListener '" + tl.getName()
-
+
"' threw exception: " + e.getMessage(), e);
-
throw se;
-
}
-
}
-
}
-
-
public void notifyTriggerListenersComplete(JobExecutionContext jec,
-
CompletedExecutionInstruction instCode)
throws SchedulerException {
-
// build a list of all trigger listeners that are to be notified...
-
List<TriggerListener> triggerListeners = buildTriggerListenerList();
-
-
// notify all trigger listeners in the list
-
for(TriggerListener tl: triggerListeners) {
-
try {
-
if(!matchTriggerListener(tl, jec.getTrigger().getKey()))
-
continue;
-
tl.triggerComplete(jec.getTrigger(), jec, instCode);
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"TriggerListener '" + tl.getName()
-
+
"' threw exception: " + e.getMessage(), e);
-
throw se;
-
}
-
}
-
}
-
-
public void notifyJobListenersToBeExecuted(JobExecutionContext jec)
-
throws SchedulerException {
-
// build a list of all job listeners that are to be notified...
-
List<JobListener> jobListeners = buildJobListenerList();
-
-
// notify all job listeners
-
for(JobListener jl: jobListeners) {
-
try {
-
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
-
continue;
-
jl.jobToBeExecuted(jec);
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"JobListener '" + jl.getName() +
"' threw exception: "
-
+ e.getMessage(), e);
-
throw se;
-
}
-
}
-
}
-
-
public void notifyJobListenersWasVetoed(JobExecutionContext jec)
-
throws SchedulerException {
-
// build a list of all job listeners that are to be notified...
-
List<JobListener> jobListeners = buildJobListenerList();
-
-
// notify all job listeners
-
for(JobListener jl: jobListeners) {
-
try {
-
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
-
continue;
-
jl.jobExecutionVetoed(jec);
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"JobListener '" + jl.getName() +
"' threw exception: "
-
+ e.getMessage(), e);
-
throw se;
-
}
-
}
-
}
-
-
public void notifyJobListenersWasExecuted(JobExecutionContext jec,
-
JobExecutionException je)
throws SchedulerException {
-
// build a list of all job listeners that are to be notified...
-
List<JobListener> jobListeners = buildJobListenerList();
-
-
// notify all job listeners
-
for(JobListener jl: jobListeners) {
-
try {
-
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
-
continue;
-
jl.jobWasExecuted(jec, je);
-
}
catch (Exception e) {
-
SchedulerException se =
new SchedulerException(
-
"JobListener '" + jl.getName() +
"' threw exception: "
-
+ e.getMessage(), e);
-
throw se;
-
}
-
}
-
}
-
-
public void notifySchedulerListenersError(String msg, SchedulerException se) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.schedulerError(msg, se);
-
}
catch (Exception e) {
-
getLog()
-
.error(
-
"Error while notifying SchedulerListener of error: ",
-
e);
-
getLog().error(
-
" Original error (for notification) was: " + msg, se);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersSchduled(Trigger trigger) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobScheduled(trigger);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of scheduled job."
-
+
" Triger=" + trigger.getKey(), e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersUnscheduled(TriggerKey triggerKey) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
if(triggerKey ==
null)
-
sl.schedulingDataCleared();
-
else
-
sl.jobUnscheduled(triggerKey);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of unscheduled job."
-
+
" Triger=" + (triggerKey ==
null ?
"ALL DATA" : triggerKey), e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersFinalized(Trigger trigger) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.triggerFinalized(trigger);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of finalized trigger."
-
+
" Triger=" + trigger.getKey(), e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersPausedTrigger(TriggerKey triggerKey) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.triggerPaused(triggerKey);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of paused trigger: "
-
+ triggerKey, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersPausedTriggers(String group) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.triggersPaused(group);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of paused trigger group."
-
+ group, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersResumedTrigger(TriggerKey key) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.triggerResumed(key);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of resumed trigger: "
-
+ key, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersResumedTriggers(String group) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.triggersResumed(group);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of resumed group: "
-
+ group, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersPausedJob(JobKey key) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobPaused(key);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of paused job: "
-
+ key, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersPausedJobs(String group) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobsPaused(group);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of paused job group: "
-
+ group, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersResumedJob(JobKey key) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobResumed(key);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of resumed job: "
-
+ key, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersResumedJobs(String group) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobsResumed(group);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of resumed job group: "
-
+ group, e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersInStandbyMode() {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.schedulerInStandbyMode();
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of inStandByMode.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersStarted() {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.schedulerStarted();
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of startup.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersStarting() {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for (SchedulerListener sl : schedListeners) {
-
try {
-
sl.schedulerStarting();
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of startup.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersShutdown() {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.schedulerShutdown();
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of shutdown.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersShuttingdown() {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.schedulerShuttingdown();
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of shutdown.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersJobAdded(JobDetail jobDetail) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobAdded(jobDetail);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of JobAdded.",
-
e);
-
}
-
}
-
}
-
-
public void notifySchedulerListenersJobDeleted(JobKey jobKey) {
-
// build a list of all scheduler listeners that are to be notified...
-
List<SchedulerListener> schedListeners = buildSchedulerListenerList();
-
-
// notify all scheduler listeners
-
for(SchedulerListener sl: schedListeners) {
-
try {
-
sl.jobDeleted(jobKey);
-
}
catch (Exception e) {
-
getLog().error(
-
"Error while notifying SchedulerListener of JobAdded.",
-
e);
-
}
-
}
-
}
-
-
public void setJobFactory(JobFactory factory) throws SchedulerException {
-
-
if(factory ==
null) {
-
throw
new IllegalArgumentException(
"JobFactory cannot be set to null!");
-
}
-
-
getLog().info(
"JobFactory set to: " + factory);
-
-
this.jobFactory = factory;
-
}
-
-
public JobFactory getJobFactory() {
-
return jobFactory;
-
}
-
-
-
/**
-
* Interrupt all instances of the identified InterruptableJob executing in
-
* this Scheduler instance.
-
*
-
* <p>
-
* This method is not cluster aware. That is, it will only interrupt
-
* instances of the identified InterruptableJob currently executing in this
-
* Scheduler instance, not across the entire cluster.
-
* </p>
-
*
-
* @see org.quartz.core.RemotableQuartzScheduler#interrupt(JobKey)
-
*/
-
public boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException {
-
-
List<JobExecutionContext> jobs = getCurrentlyExecutingJobs();
-
-
JobDetail jobDetail =
null;
-
Job job =
null;
-
-
boolean interrupted =
false;
-
-
for(JobExecutionContext jec : jobs) {
-
jobDetail = jec.getJobDetail();
-
if (jobKey.equals(jobDetail.getKey())) {
-
job = jec.getJobInstance();
-
if (job
instanceof InterruptableJob) {
-
((InterruptableJob)job).interrupt();
-
interrupted =
true;
-
}
else {
-
throw
new UnableToInterruptJobException(
-
"Job " + jobDetail.getKey() +
-
" can not be interrupted, since it does not implement " +
-
InterruptableJob.class.getName());
-
}
-
}
-
}
-
-
return interrupted;
-
}
-
-
/**
-
* Interrupt the identified InterruptableJob executing in this Scheduler instance.
-
*
-
* <p>
-
* This method is not cluster aware. That is, it will only interrupt
-
* instances of the identified InterruptableJob currently executing in this
-
* Scheduler instance, not across the entire cluster.
-
* </p>
-
*
-
* @see org.quartz.core.RemotableQuartzScheduler#interrupt(JobKey)
-
*/
-
public boolean interrupt(String fireInstanceId) throws UnableToInterruptJobException {
-
List<JobExecutionContext> jobs = getCurrentlyExecutingJobs();
-
-
Job job =
null;
-
-
for(JobExecutionContext jec : jobs) {
-
if (jec.getFireInstanceId().equals(fireInstanceId)) {
-
job = jec.getJobInstance();
-
if (job
instanceof InterruptableJob) {
-
((InterruptableJob)job).interrupt();
-
return
true;
-
}
else {
-
throw
new UnableToInterruptJobException(
-
"Job " + jec.getJobDetail().getKey() +
-
" can not be interrupted, since it does not implement " +
-
InterruptableJob.class.getName());
-
}
-
}
-
}
-
-
return
false;
-
}
-
-
private void shutdownPlugins() {
-
java.util.Iterator<SchedulerPlugin> itr = resources.getSchedulerPlugins().iterator();
-
while (itr.hasNext()) {
-
SchedulerPlugin plugin = itr.next();
-
plugin.shutdown();
-
}
-
}
-
-
private void startPlugins() {
-
java.util.Iterator<SchedulerPlugin> itr = resources.getSchedulerPlugins().iterator();
-
while (itr.hasNext()) {
-
SchedulerPlugin plugin = itr.next();
-
plugin.start();
-
}
-
}
-
-
}
-
-
/////////////////////////////////////////////////////////////////////////////
-
//
-
// ErrorLogger - Scheduler Listener Class
-
//
-
/////////////////////////////////////////////////////////////////////////////
-
-
class ErrorLogger extends SchedulerListenerSupport {
-
ErrorLogger() {
-
}
-
-
@Override
-
public void schedulerError(String msg, SchedulerException cause) {
-
getLog().error(msg, cause);
-
}
-
-
}
-
-
/////////////////////////////////////////////////////////////////////////////
-
//
-
// ExecutingJobsManager - Job Listener Class
-
//
-
/////////////////////////////////////////////////////////////////////////////
-
-
class ExecutingJobsManager implements JobListener {
-
HashMap<String, JobExecutionContext> executingJobs =
new HashMap<String, JobExecutionContext>();
-
-
AtomicInteger numJobsFired =
new AtomicInteger(
0);
-
-
ExecutingJobsManager() {
-
}
-
-
public String getName() {
-
return getClass().getName();
-
}
-
-
public int getNumJobsCurrentlyExecuting() {
-
synchronized (executingJobs) {
-
return executingJobs.size();
-
}
-
}
-
-
public void jobToBeExecuted(JobExecutionContext context) {
-
numJobsFired.incrementAndGet();
-
-
synchronized (executingJobs) {
-
executingJobs
-
.put(((OperableTrigger)context.getTrigger()).getFireInstanceId(), context);
-
}
-
}
-
-
public void jobWasExecuted(JobExecutionContext context,
-
JobExecutionException jobException) {
-
synchronized (executingJobs) {
-
executingJobs.remove(((OperableTrigger)context.getTrigger()).getFireInstanceId());
-
}
-
}
-
-
public int getNumJobsFired() {
-
return numJobsFired.get();
-
}
-
-
public List<JobExecutionContext> getExecutingJobs() {
-
synchronized (executingJobs) {
-
return java.util.Collections.unmodifiableList(
new ArrayList<JobExecutionContext>(
-
executingJobs.values()));
-
}
-
}
-
-
public void jobExecutionVetoed(JobExecutionContext context) {
-
-
}
-
}
org.quartz.core.QuartzSchedulerThread
-
-
/*
-
* 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.core;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
import java.util.Random;
-
import java.util.concurrent.atomic.AtomicBoolean;
-
-
import org.quartz.JobPersistenceException;
-
import org.quartz.SchedulerException;
-
import org.quartz.Trigger;
-
import org.quartz.Trigger.CompletedExecutionInstruction;
-
import org.quartz.spi.JobStore;
-
import org.quartz.spi.OperableTrigger;
-
import org.quartz.spi.TriggerFiredBundle;
-
import org.quartz.spi.TriggerFiredResult;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
/**
-
* <p>
-
* The thread responsible for performing the work of firing <code>{@link Trigger}</code>
-
* s that are registered with the <code>{@link QuartzScheduler}</code>.
-
* </p>
-
*
-
* @see QuartzScheduler
-
* @see org.quartz.Job
-
* @see Trigger
-
*
-
* @author James House
-
*/
-
public
class QuartzSchedulerThread extends Thread {
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Data members.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
private QuartzScheduler qs;
-
-
private QuartzSchedulerResources qsRsrcs;
-
-
private
final Object sigLock =
new Object();
-
-
private
boolean signaled;
-
private
long signaledNextFireTime;
-
-
private
boolean paused;
-
-
private AtomicBoolean halted;
-
-
private Random random =
new Random(System.currentTimeMillis());
-
-
// When the scheduler finds there is no current trigger to fire, how long
-
// it should wait until checking again...
-
private
static
long DEFAULT_IDLE_WAIT_TIME =
30L *
1000L;
-
-
private
long idleWaitTime = DEFAULT_IDLE_WAIT_TIME;
-
-
private
int idleWaitVariablness =
7 *
1000;
-
-
private
final Logger log = LoggerFactory.getLogger(getClass());
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Constructors.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
/**
-
* <p>
-
* Construct a new <code>QuartzSchedulerThread</code> for the given
-
* <code>QuartzScheduler</code> as a non-daemon <code>Thread</code>
-
* with normal priority.
-
* </p>
-
*/
-
QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs) {
-
this(qs, qsRsrcs, qsRsrcs.getMakeSchedulerThreadDaemon(), Thread.NORM_PRIORITY);
-
}
-
-
/**
-
* <p>
-
* Construct a new <code>QuartzSchedulerThread</code> for the given
-
* <code>QuartzScheduler</code> as a <code>Thread</code> with the given
-
* attributes.
-
* </p>
-
*/
-
QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs,
boolean setDaemon,
int threadPrio) {
-
super(qs.getSchedulerThreadGroup(), qsRsrcs.getThreadName());
-
this.qs = qs;
-
this.qsRsrcs = qsRsrcs;
-
this.setDaemon(setDaemon);
-
if(qsRsrcs.isThreadsInheritInitializersClassLoadContext()) {
-
log.info(
"QuartzSchedulerThread Inheriting ContextClassLoader of thread: " + Thread.currentThread().getName());
-
this.setContextClassLoader(Thread.currentThread().getContextClassLoader());
-
}
-
-
this.setPriority(threadPrio);
-
-
// start the underlying thread, but put this object into the 'paused'
-
// state
-
// so processing doesn't start yet...
-
paused =
true;
-
halted =
new AtomicBoolean(
false);
-
}
-
-
/*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*
-
* Interface.
-
*
-
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
*/
-
-
void setIdleWaitTime(long waitTime) {
-
idleWaitTime = waitTime;
-
idleWaitVariablness = (
int) (waitTime *
0.2);
-
}
-
-
private long getRandomizedIdleWaitTime() {
-
return idleWaitTime - random.nextInt(idleWaitVariablness);
-
}
-
-
/**
-
* <p>
-
* Signals the main processing loop to pause at the next possible point.
-
* </p>
-
*/
-
void togglePause(boolean pause) {
-
synchronized (sigLock) {
-
paused = pause;
-
-
if (paused) {
-
signalSchedulingChange(
0);
-
}
else {
-
sigLock.notifyAll();
-
}
-
}
-
}
-
-
/**
-
* <p>
-
* Signals the main processing loop to pause at the next possible point.
-
* </p>
-
*/
-
void halt(boolean wait) {
-
synchronized (sigLock) {
-
halted.set(
true);
-
-
if (paused) {
-
sigLock.notifyAll();
-
}
else {
-
signalSchedulingChange(
0);
-
}
-
}
-
-
if (wait) {
-
boolean interrupted =
false;
-
try {
-
while (
true) {
-
try {
-
join();
-
break;
-
}
catch (InterruptedException _) {
-
interrupted =
true;
-
}
-
}
-
}
finally {
-
if (interrupted) {
-
Thread.currentThread().interrupt();
-
}
-
}
-
}
-
}
-
-
boolean isPaused() {
-
return paused;
-
}
-
-
/**
-
* <p>
-
* Signals the main processing loop that a change in scheduling has been
-
* made - in order to interrupt any sleeping that may be occuring while
-
* waiting for the fire time to arrive.
-
* </p>
-
*
-
* @param candidateNewNextFireTime the time (in millis) when the newly scheduled trigger
-
* will fire. If this method is being called do to some other even (rather
-
* than scheduling a trigger), the caller should pass zero (0).
-
*/
-
public void signalSchedulingChange(long candidateNewNextFireTime) {
-
synchronized(sigLock) {
-
signaled =
true;
-
signaledNextFireTime = candidateNewNextFireTime;
-
sigLock.notifyAll();
-
}
-
}
-
-
public void clearSignaledSchedulingChange() {
-
synchronized(sigLock) {
-
signaled =
false;
-
signaledNextFireTime =
0;
-
}
-
}
-
-
public boolean isScheduleChanged() {
-
synchronized(sigLock) {
-
return signaled;
-
}
-
}
-
-
public long getSignaledNextFireTime() {
-
synchronized(sigLock) {
-
return signaledNextFireTime;
-
}
-
}
-
-
/**
-
* <p>
-
* The main processing loop of the <code>QuartzSchedulerThread</code>.
-
* </p>
-
*/
-
@Override
-
public void run() {
-
int acquiresFailed =
0;
-
-
while (!halted.get()) {
-
try {
-
// check if we're supposed to pause...
-
synchronized (sigLock) {
-
while (paused && !halted.get()) {
-
try {
-
// wait until togglePause(false) is called...
-
sigLock.wait(
1000L);
-
}
catch (InterruptedException ignore) {
-
}
-
-
// reset failure counter when paused, so that we don't
-
// wait again after unpausing
-
acquiresFailed =
0;
-
}
-
-
if (halted.get()) {
-
break;
-
}
-
}
-
-
// wait a bit, if reading from job store is consistently
-
// failing (e.g. DB is down or restarting)..
-
if (acquiresFailed >
1) {
-
try {
-
long delay = computeDelayForRepeatedErrors(qsRsrcs.getJobStore(), acquiresFailed);
-
Thread.sleep(delay);
-
}
catch (Exception ignore) {
-
}
-
}
-
//todo 获取可用线程的数量
-
int availThreadCount = qsRsrcs.getThreadPool().blockForAvailableThreads();
-
-
//todo 将永远是true,由于blockForAvailableThreads的语义...
-
if(availThreadCount >
0) {
// will always be true, due to semantics of blockForAvailableThreads...
-
-
//todo 定义触发器集合
-
List<OperableTrigger> triggers;
-
-
long now = System.currentTimeMillis();
-
-
clearSignaledSchedulingChange();
-
try {
-
//todo 从jobStore中获取下次要触发的触发器集合
-
// idleWaitTime == 30L * 1000L; 当调度程序发现没有当前触发器要触发,它应该等待多长时间再检查...
-
triggers = qsRsrcs.getJobStore().acquireNextTriggers(
-
now + idleWaitTime, Math.min(availThreadCount, qsRsrcs.getMaxBatchSize()), qsRsrcs.getBatchTimeWindow());
-
acquiresFailed =
0;
-
if (log.isDebugEnabled())
-
log.debug(
"batch acquisition of " + (triggers ==
null ?
0 : triggers.size()) +
" triggers");
-
}
catch (JobPersistenceException jpe) {
-
if (acquiresFailed ==
0) {
-
qs.notifySchedulerListenersError(
-
"An error occurred while scanning for the next triggers to fire.",
-
jpe);
-
}
-
if (acquiresFailed < Integer.MAX_VALUE)
-
acquiresFailed++;
-
continue;
-
}
catch (RuntimeException e) {
-
if (acquiresFailed ==
0) {
-
getLog().error(
"quartzSchedulerThreadLoop: RuntimeException "
-
+e.getMessage(), e);
-
}
-
if (acquiresFailed < Integer.MAX_VALUE)
-
acquiresFailed++;
-
continue;
-
}
-
-
//todo 判断返回的触发器存在
-
if (triggers !=
null && !triggers.isEmpty()) {
-
-
now = System.currentTimeMillis();
-
//todo 若有没有触发的Trigger,下次触发时间 next_fire_time 这个会在启动的时候有个默认的misfire机制,
-
// setNextFireTime();
-
// 即start()启动时候的当前时间。
-
long triggerTime = triggers.get(
0).getNextFireTime().getTime();
-
long timeUntilTrigger = triggerTime - now;
-
while(timeUntilTrigger >
2) {
-
synchronized (sigLock) {
-
if (halted.get()) {
-
break;
-
}
-
if (!isCandidateNewTimeEarlierWithinReason(triggerTime,
false)) {
-
try {
-
// we could have blocked a long while
-
// on 'synchronize', so we must recompute
-
now = System.currentTimeMillis();
-
timeUntilTrigger = triggerTime - now;
-
if(timeUntilTrigger >=
1)
-
sigLock.wait(timeUntilTrigger);
-
}
catch (InterruptedException ignore) {
-
}
-
}
-
}
-
if(releaseIfScheduleChangedSignificantly(triggers, triggerTime)) {
-
break;
-
}
-
now = System.currentTimeMillis();
-
timeUntilTrigger = triggerTime - now;
-
}
-
-
// this happens if releaseIfScheduleChangedSignificantly decided to release triggers
-
//todo 这种情况发生,如果releaseIfScheduleChangedSignificantly 决定 释放Trigger
-
if(triggers.isEmpty())
-
continue;
-
-
// set triggers to 'executing'
-
//todo 将触发器设置为“正在执行”
-
List<TriggerFiredResult> bndles =
new ArrayList<TriggerFiredResult>();
-
-
boolean goAhead =
true;
-
synchronized(sigLock) {
-
goAhead = !halted.get();
-
}
-
if(goAhead) {
-
try {
-
//todo 通知JobStore调度程序现在正在触发其先前已获取(保留)的给定触发器(执行其关联的作业)。
-
List<TriggerFiredResult> res = qsRsrcs.getJobStore().triggersFired(triggers);
-
if(res !=
null)
-
bndles = res;
-
}
catch (SchedulerException se) {
-
qs.notifySchedulerListenersError(
-
"An error occurred while firing triggers '"
-
+ triggers +
"'", se);
-
//QTZ-179 : a problem occurred interacting with the triggers from the db
-
//we release them and loop again
-
for (
int i =
0; i < triggers.size(); i++) {
-
qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i));
-
}
-
continue;
-
}
-
-
}
-
-
//todo 循环List<TriggerFiredResult> bndles 集合,获取TriggerFiredResult和TriggerFiredBundle等
-
for (
int i =
0; i < bndles.size(); i++) {
-
TriggerFiredResult result = bndles.get(i);
-
TriggerFiredBundle bndle = result.getTriggerFiredBundle();
-
Exception exception = result.getException();
-
-
if (exception
instanceof RuntimeException) {
-
getLog().error(
"RuntimeException while firing trigger " + triggers.get(i), exception);
-
qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i));
-
continue;
-
}
-
-
// it's possible to get 'null' if the triggers was paused,
-
// blocked, or other similar occurrences that prevent it being
-
// fired at this time... or if the scheduler was shutdown (halted)
-
//todo 如果触发器被暂停,阻塞或其他类似的事件阻止它在这时被触发,
-
// 或者如果调度器被关闭(暂停),则可以获得'null'
-
if (bndle ==
null) {
-
qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i));
-
continue;
-
}
-
-
JobRunShell shell =
null;
-
try {
-
-
-
//todo 创建 JobRunShell ,并初始化
-
shell = qsRsrcs.getJobRunShellFactory().createJobRunShell(bndle);
-
shell.initialize(qs);
-
-
-
}
catch (SchedulerException se) {
-
qsRsrcs.getJobStore().triggeredJobComplete(triggers.get(i), bndle.getJobDetail(), CompletedExecutionInstruction.SET_ALL_JOB_TRIGGERS_ERROR);
-
continue;
-
}
-
-
//todo 提交任务到 worker 线程.......
-
if (qsRsrcs.getThreadPool().runInThread(shell) ==
false) {
-
// this case should never happen, as it is indicative of the
-
// scheduler being shutdown or a bug in the thread pool or
-
// a thread pool being used concurrently - which the docs
-
// say not to do...
-
//todo 这种情况不应该发生,因为它表示调度程序正在关闭或线程池或线程池中并发使用的错误 - 文档说不要这样做...
-
getLog().error(
"ThreadPool.runInThread() return false!");
-
qsRsrcs.getJobStore().triggeredJobComplete(triggers.get(i), bndle.getJobDetail(), CompletedExecutionInstruction.SET_ALL_JOB_TRIGGERS_ERROR);
-
}
-
-
}
-
-
continue;
// while (!halted)
-
}
-
}
else {
// if(availThreadCount > 0)
-
// should never happen, if threadPool.blockForAvailableThreads() follows contract
-
//todo 应该永远不会发生,如果threadPool.blockForAvailableThreads()遵循约定
-
continue;
// while (!halted)
-
}
-
-
long now = System.currentTimeMillis();
-
long waitTime = now + getRandomizedIdleWaitTime();
-
long timeUntilContinue = waitTime - now;
-
-
//todo idleWaitTime == 30L * 1000L; idleWaitVariablness == 7 * 1000;
-
// 计算getRandomizedIdleWaitTime()的值 : idleWaitTime - random.nextInt(idleWaitVariablness);
-
-
synchronized(sigLock) {
-
try {
-
if(!halted.get()) {
-
// QTZ-336 A job might have been completed in the mean time and we might have
-
// missed the scheduled changed signal by not waiting for the notify() yet
-
// Check that before waiting for too long in case this very job needs to be
-
// scheduled very soon
-
if (!isScheduleChanged()) {
-
sigLock.wait(timeUntilContinue);
-
}
-
}
-
}
catch (InterruptedException ignore) {
-
}
-
}
-
-
}
catch(RuntimeException re) {
-
getLog().error(
"Runtime error occurred in main trigger firing loop.", re);
-
}
-
}
// while (!halted)
-
-
// drop references to scheduler stuff to aid garbage collection...
-
//todo 删除对调度程序内容的引用以帮助垃圾回收...
-
qs =
null;
-
qsRsrcs =
null;
-
}
-
-
private
static
final
long MIN_DELAY =
20;
-
private
static
final
long MAX_DELAY =
600000;
-
-
private static long computeDelayForRepeatedErrors(JobStore jobStore, int acquiresFailed) {
-
long delay;
-
try {
-
delay = jobStore.getAcquireRetryDelay(acquiresFailed);
-
}
catch (Exception ignored) {
-
// we're trying to be useful in case of error states, not cause
-
// additional errors..
-
delay =
100;
-
}
-
-
-
// sanity check per getAcquireRetryDelay specification
-
if (delay < MIN_DELAY)
-
delay = MIN_DELAY;
-
if (delay > MAX_DELAY)
-
delay = MAX_DELAY;
-
-
return delay;
-
}
-
-
private boolean releaseIfScheduleChangedSignificantly(
-
List<OperableTrigger> triggers, long triggerTime) {
-
if (isCandidateNewTimeEarlierWithinReason(triggerTime,
true)) {
-
// above call does a clearSignaledSchedulingChange()
-
for (OperableTrigger trigger : triggers) {
-
qsRsrcs.getJobStore().releaseAcquiredTrigger(trigger);
-
}
-
triggers.clear();
-
return
true;
-
}
-
return
false;
-
}
-
-
private boolean isCandidateNewTimeEarlierWithinReason(long oldTime, boolean clearSignal) {
-
-
// So here's the deal: We know due to being signaled that 'the schedule'
-
// has changed. We may know (if getSignaledNextFireTime() != 0) the
-
// new earliest fire time. We may not (in which case we will assume
-
// that the new time is earlier than the trigger we have acquired).
-
// In either case, we only want to abandon our acquired trigger and
-
// go looking for a new one if "it's worth it". It's only worth it if
-
// the time cost incurred to abandon the trigger and acquire a new one
-
// is less than the time until the currently acquired trigger will fire,
-
// otherwise we're just "thrashing" the job store (e.g. database).
-
//
-
// So the question becomes when is it "worth it"? This will depend on
-
// the job store implementation (and of course the particular database
-
// or whatever behind it). Ideally we would depend on the job store
-
// implementation to tell us the amount of time in which it "thinks"
-
// it can abandon the acquired trigger and acquire a new one. However
-
// we have no current facility for having it tell us that, so we make
-
// a somewhat educated but arbitrary guess ;-).
-
-
synchronized(sigLock) {
-
-
if (!isScheduleChanged())
-
return
false;
-
-
boolean earlier =
false;
-
-
if(getSignaledNextFireTime() ==
0)
-
earlier =
true;
-
else
if(getSignaledNextFireTime() < oldTime )
-
earlier =
true;
-
-
if(earlier) {
-
// so the new time is considered earlier, but is it enough earlier?
-
long diff = oldTime - System.currentTimeMillis();
-
if(diff < (qsRsrcs.getJobStore().supportsPersistence() ?
70L :
7L))
-
earlier =
false;
-
}
-
-
if(clearSignal) {
-
clearSignaledSchedulingChange();
-
}
-
-
return earlier;
-
}
-
}
-
-
public Logger getLog() {
-
return log;
-
}
-
-
}
// end of QuartzSchedulerThread
转载:https://blog.csdn.net/zhanglong_4444/article/details/104322964
查看评论