📄 quartzscheduler.java
字号:
/* * Copyright James House (c) 2001-2004 * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: 1. * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. 2. Redistributions in * binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package org.quartz.core;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;import java.util.ArrayList;import java.util.Collections;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Random;import java.util.Set;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.quartz.Calendar;import org.quartz.Job;import org.quartz.InterruptableJob;import org.quartz.JobDetail;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobListener;import org.quartz.JobPersistenceException;import org.quartz.ObjectAlreadyExistsException;import org.quartz.Scheduler;import org.quartz.SchedulerContext;import org.quartz.SchedulerException;import org.quartz.SchedulerListener;import org.quartz.Trigger;import org.quartz.TriggerListener;import org.quartz.UnableToInterruptJobException;import org.quartz.impl.SchedulerRepository;import org.quartz.spi.SchedulerPlugin;import org.quartz.spi.SchedulerSignaler;/** * <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>// TODO: more docs... * * @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. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public static final String VERSION_MAJOR = "@version.major@"; public static final String VERSION_MINOR = "@version.minor@"; public static final String VERSION_ITERATION = "@version.iteration@"; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private QuartzSchedulerResources resources; private QuartzSchedulerThread schedThread; private ThreadGroup threadGroup; private SchedulerContext context = new SchedulerContext(); private HashMap jobListeners = new HashMap(10); private ArrayList globalJobListeners = new ArrayList(10); private HashMap triggerListeners = new HashMap(10); private ArrayList globalTriggerListeners = new ArrayList(10); private ArrayList schedulerListeners = new ArrayList(10); private ArrayList schedulerPlugins = new ArrayList(10); ExecutingJobsManager jobMgr = null; ErrorLogger errLogger = null; private SchedulerSignaler signaler; private Random random = new Random(); private ArrayList holdToPreventGC = new ArrayList(5); private boolean signalOnSchedulingChange = true; private boolean closed = false; private Date initialStart = null; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * <p> * Create a <code>QuartzScheduler</code> with the given configuration * properties. * </p> * * @see QuartzSchedulerResources */ public QuartzScheduler(QuartzSchedulerResources resources, SchedulingContext ctxt, long idleWaitTime, long dbRetryInterval) throws SchedulerException { this.resources = resources; try { bind(); } catch (Exception re) { throw new SchedulerException( "Unable to bind scheduler to RMI Registry.", re); } this.schedThread = new QuartzSchedulerThread(this, resources, ctxt); if (idleWaitTime > 0) this.schedThread.setIdleWaitTime(idleWaitTime); if (dbRetryInterval > 0) this.schedThread.setDbFailureRetryInterval(dbRetryInterval); jobMgr = new ExecutingJobsManager(); addGlobalJobListener(jobMgr); errLogger = new ErrorLogger(); addSchedulerListener(errLogger); signaler = new SchedulerSignalerImpl(this); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public String getVersion() { return getVersionMajor() + "." + getVersionMinor() + "." + getVersionIteration(); } public String getVersionMajor() { return VERSION_MAJOR; } public String getVersionMinor() { return VERSION_MINOR; } public String getVersionIteration() { return VERSION_ITERATION; } public SchedulerSignaler getSchedulerSignaler() { return signaler; } public static Log getLog() { return LogFactory.getLog(QuartzScheduler.class); } /** * <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 = (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()); } registry.rebind(resources.getUniqueIdentifier(), exportable); getLog().info("Scheduler bound to RMI registry."); } /** * <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()); try { registry.unbind(resources.getUniqueIdentifier()); UnicastRemoteObject.unexportObject(this, true); } catch (java.rmi.NotBoundException nbe) { } getLog().info("Scheduler un-bound from 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 <code>QuartzScheduler</code>. * </p> */ public ThreadGroup getSchedulerThreadGroup() { if (threadGroup == null) { threadGroup = new ThreadGroup("QuartzScheduler:" + getSchedulerName()); } 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; } /////////////////////////////////////////////////////////////////////////// /// /// Schedululer 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> */ public void start() throws SchedulerException { if (closed) throw new SchedulerException( "The Scheduler cannot be restarted after shutdown() has been called."); schedThread.togglePause(false); if (initialStart == null) { initialStart = new Date(); startPlugins(); } getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " started."); } /** * <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 pause() { schedThread.togglePause(true); getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " paused."); } /** * <p> * Reports whether the <code>Scheduler</code> is paused. * </p> */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -