初识Quartz之Scheduler组件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/carson0408/article/details/79861016

        之前在Trigger组件中的withSchedule(ScheduleBuilder scheduleBuilder)方法中,接触过ScheduleBuilder抽象类,通过将ScheduleBuilder对象传入用于调度参数的设置。本文主要讲述的是Scheduler组件,Scheduler组件主要用于将前文讲述的Job组件中的JobDetail对象和Trigger对象绑定在一起,进行完整的调度运行。

1.SchedulerFactory

        之前JobDetail和Trigger创建对象都是使用对应的Builder类进行创建的,而Scheduler对象则稍有不同,而是使用工厂类进行创建。首先创建一个工厂类对象,即SchedulerFactory对象,其中SchedulerFactory是一个接口,里面有三个关于创建Scheduler对象的方法。

public interface SchedulerFactory {

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

    /**
     * <p>
     * Returns a client-usable handle to a <code>Scheduler</code>.
     * </p>
     * 
     * @throws SchedulerException
     *           if there is a problem with the underlying <code>Scheduler</code>.
     */
    Scheduler getScheduler() throws SchedulerException;

    /**
     * <p>
     * Returns a handle to the Scheduler with the given name, if it exists.
     * </p>
     */
    Scheduler getScheduler(String schedName) throws SchedulerException;

    /**
     * <p>
     * Returns handles to all known Schedulers (made by any SchedulerFactory
     * within this jvm.).
     * </p>
     */
    Collection<Scheduler> getAllSchedulers() throws SchedulerException;

}

        创建SchedulerFactory对象需要找到SchedulerFactory接口的实现类,本文讲述的实现类是StdSchedulerFactory,该类实现了接口的三个方法,因此创建完SchedulerFactory对象后,可以调用相应的方法获取Scheduler对象,如以下代码所示:

SchedulerFactory sf=new StdSchedulerFactory();
Scheduler scheduler=sf.getScheduler();

2.启动与绑定

        Scheduler也是一个接口,它有三个实现类,分别是:StdScheduler、RemoteScheduler、RemoteMBeanScheduler(抽象类,其中JBoss4RMIRemoteMBeanScheduler是抽象类的实现类)。本文以StdScheduler为例,关于scheduler对象的启动,StdScheduler有两个启动的方法,一个是即时启动,另一个是延迟启动。

public void start() throws SchedulerException {
        sched.start();
    }

    /**
     * <p>
     * Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>.
     * </p>
     */
    public void startDelayed(int seconds) throws SchedulerException {
        sched.startDelayed(seconds);
    }

        其中即时启动调用了对象名为sched的start()方法,延迟启动则是在方法内部调用了对象名为sched的startDelayed(int seconds)方法,而在StdScheduler类声明变量时,已经声明了private QuartzScheduler sched;说明sched是QuartzScheduler类型的,可以通过查看QuartzScheduler的源码,了解start()和startDelayed(int seconds)方法。

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

        if (initialStart == null) {
            initialStart = new Date();
            this.resources.getJobStore().schedulerStarted();            
            startPlugins();
        } else {
            resources.getJobStore().schedulerResumed();
        }

        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 secheduler after startup delay.", se);
                }
            }
        });
        t.start();
    }

        其中可以看出start()是即时启动,而start(int seconds)就是在方法里定义了一个线程,利用Thread的sleep方法进行等待实现延迟启动。



       至于绑定,调用scheduler对象的scheduleJob(JobDetail jobDetail, Trigger trigger)方法。

public Date scheduleJob(JobDetail jobDetail, Trigger trigger)
        throws SchedulerException {
        return sched.scheduleJob(jobDetail, trigger);
    }

         以下是QuartzScheduler类的scheduleJob(JobDetail jobDetail, Trigger trigger)方法,该方法对JobDetail对象和Trigger对象进行绑定。并且传入scheduler对象中。

public Date scheduleJob(JobDetail jobDetail,
            Trigger trigger) throws SchedulerException {
        validateState();

        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;

        if (trigger.getJobKey() == null) {
            trig.setJobKey(jobDetail.getKey());
        } else if (!trigger.getJobKey().equals(jobDetail.getKey())) {
            throw new SchedulerException(
                "Trigger does not reference given job!");
        }

        trig.validate();

        Calendar cal = null;
        if (trigger.getCalendarName() != null) {
            cal = resources.getJobStore().retrieveCalendar(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().storeJobAndTrigger(jobDetail, trig);
        notifySchedulerListenersJobAdded(jobDetail);
        notifySchedulerThread(trigger.getNextFireTime().getTime());
        notifySchedulerListenersSchduled(trigger);

        return ft;
    }

         

         以上分析可知,首先创建一个SchedulerFactory对象,通过SchedulerFactory对象的方法构造Scheduler对象,其中Scheduler是一个抽象类,如果使用scheduler对象的start()方法启动,则需要调用QuartzScheduler类中的start()方法。然后调用QuartzScheduler类中的schduleJob()方法进行trigger和detail的绑定。


猜你喜欢

转载自blog.csdn.net/carson0408/article/details/79861016
今日推荐