Quertz作业调度

第0章:简介

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs。


第0节:参考网站

http://www.ibm.com/developerworks/cn/java/j-quartz/

http://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/

官网:http://www.quartz-scheduler.org/

官网文档:http://www.quartz-scheduler.org/documentation

开源中国:http://www.oschina.net/p/quartz

百度百科:http://baike.baidu.com/subview/1002067/5810766.htm#viewPageContent


第1节:maven座标

        <!--任务调度-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>1.8.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

第2节:札记

(1)Quartz 调度包的两个基本单元是作业和触发器。作业是能够调度的可执行任务,触发器 提供了对作业的调度。

(2)Quartz 允许在不丢失作业本身或作业的上下文的情况下,修改调度触发器。而且,任何单个的作业都可以有多个触发器与其关联。


第1章:实例

(1)quertz任务调度器工具类(ScheduleService.java)

package com.mcc.core.quartz;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;

/**
 * 任务调度器服务,用到quartz包
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 13-12-20  上午10:54
 */
public abstract class ScheduleService {
    // members
    private static Logger logger = LoggerFactory.getLogger(ScheduleService.class);
    // 任务调度器
    protected Scheduler scheduler;

    // static block

    // constructors

    // properties

    // public methods

    /**
     * 添加任务调度器
     *
     * @param scheduler 调度器
     */
    public abstract void addScheduler(Scheduler scheduler);

    /**
     * 通用执行任务方法,并按照cronExpression执行任务
     *
     * @param jobClazz       执行的任务类
     * @param groupName      JOB组
     * @param cronExpression cron表达式
     * @throws org.quartz.SchedulerException
     * @throws java.text.ParseException
     */
    public void addJob(Class jobClazz, String groupName, String cronExpression) throws SchedulerException, ParseException {
        addJob(jobClazz, groupName, cronExpression, false);
    }

    /**
     * 通用执行任务方法,并按照cronExpression执行任务
     *
     * @param jobClazz       执行的任务类
     * @param groupName      JOB组
     * @param cronExpression cron表达式
     * @param pause          是否默认暂停
     * @throws org.quartz.SchedulerException
     * @throws java.text.ParseException
     */
    public void addJob(Class jobClazz, String groupName, String cronExpression, boolean pause) throws SchedulerException, ParseException {
        addJob(null, jobClazz, groupName, cronExpression, pause);
    }

    /**
     * 通用执行任务方法,并按照cronExpression执行任务
     *
     * @param jobDetail      执行的任务
     * @param jobClazz       执行的任务类
     * @param groupName      JOB组
     * @param cronExpression cron表达式
     * @throws org.quartz.SchedulerException
     * @throws java.text.ParseException
     */
    public void addJob(JobDetail jobDetail, Class jobClazz, String groupName, String cronExpression) throws SchedulerException, ParseException {
        addJob(jobDetail, jobClazz, groupName, cronExpression, false);
    }

    /**
     * 通用执行任务方法,并按照cronExpression执行任务
     *
     * @param jobDetail      执行的任务
     * @param jobClazz       执行的任务类
     * @param groupName      JOB组, jobName = groupName + "_DETAIL", triggerName = groupName + "_TRIGGER"
     * @param cronExpression cron表达式
     * @param pause          是否默认暂停
     * @throws org.quartz.SchedulerException
     * @throws java.text.ParseException
     */
    public void addJob(JobDetail jobDetail, Class jobClazz, String groupName, String cronExpression, boolean pause) throws SchedulerException, ParseException {
        // 添加任务
        String jobName = new StringBuilder(groupName).append("_").append("DETAIL").toString();
        if (jobDetail == null) {
            jobDetail = new JobDetail();
        }
        if (groupName == null || groupName.isEmpty()) {
            groupName = Scheduler.DEFAULT_GROUP;
        }
        jobDetail.setName(jobName);
        jobDetail.setGroup(groupName);
        jobDetail.setJobClass(jobClazz);
        scheduler.addJob(jobDetail, true);
        // 添加解发器
        String triggerName = new StringBuilder(groupName).append("_").append("TRIGGER").toString();
        CronTrigger cronTrigger = new CronTrigger();
        cronTrigger.setName(triggerName);
        cronTrigger.setGroup(groupName);
        cronTrigger.setJobName(jobDetail.getName());
        cronTrigger.setJobGroup(groupName);
        cronTrigger.setCronExpression(cronExpression);
        scheduler.scheduleJob(cronTrigger);
        if (pause) {
            scheduler.pauseJob(jobName, groupName);
        }
    }

    /**
     * 暂停所有任务
     *
     * @throws org.quartz.SchedulerException
     */
    public void pausehAll() {
        try {
            scheduler.pauseAll();
        } catch (SchedulerException e) {
            logger.error("暂停所有任务失败!", e);
        }
    }

    /**
     * 暂停指定JOB
     *
     * @param jobName JOB名称
     * @throws org.quartz.SchedulerException
     */
    public void pauseJob(String jobName) {
        pauseJob(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 暂停指定JOB
     *
     * @param jobName JOB名称
     * @throws org.quartz.SchedulerException
     */
    public void pauseJob(String jobName, String groupName) {
        try {
            scheduler.pauseJob(jobName, groupName);
        } catch (SchedulerException e) {
            logger.error("暂停任务 " + jobName + " 失败!", e);
        }
    }

    /**
     * 暂停指定JOB Group
     *
     * @param groupName 组名
     * @throws org.quartz.SchedulerException
     */
    public void pauseGroup(String groupName) {
        try {
            scheduler.pauseJobGroup(groupName);
        } catch (SchedulerException e) {
            logger.error("暂停任务组 " + groupName + " 失败!", e);
        }
    }

    /**
     * 恢复所有JOB
     *
     * @throws org.quartz.SchedulerException
     */
    public void resumeAll() {
        try {
            scheduler.resumeAll();
        } catch (SchedulerException e) {
            logger.error("恢复所有任务失败!", e);
        }
    }

    /**
     * 恢复指定JOB
     *
     * @param jobName JOB名称
     * @throws org.quartz.SchedulerException
     */
    public void resumeJob(String jobName) {
        resumeJob(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 恢复指定JOB
     *
     * @param jobName JOB名称
     * @throws org.quartz.SchedulerException
     */
    public void resumeJob(String jobName, String groupName) {
        try {
            scheduler.resumeJob(jobName, groupName);
        } catch (SchedulerException e) {
            logger.error("恢复任务 " + jobName + " 失败!", e);
        }
    }

    /**
     * 恢复指定JOB Group
     *
     * @param groupName 组名
     */
    public void resumeGroup(String groupName) {
        try {
            scheduler.resumeJobGroup(groupName);
        } catch (SchedulerException e) {
            logger.error("恢复任务组失败!", e);
        }
    }

    /**
     * 获取JOB
     *
     * @param jobName JOB名称
     * @return
     * @throws org.quartz.SchedulerException
     */
    public JobDetail getJobDetail(String jobName) throws SchedulerException {
        return scheduler.getJobDetail(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 启动调度器
     *
     * @throws org.quartz.SchedulerException
     */
    public void start() throws SchedulerException {
        scheduler.start();
    }

    /**
     * 停止调度器
     *
     * @throws org.quartz.SchedulerException
     */
    public void stop() throws SchedulerException {
        scheduler.shutdown();
    }
    // protected methods

    // friendly methods

    // private methods

    // inner class

    // test main

}


(2)quartz作业TestJob.java

package com.mcc.core.test;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;

/**
 * quartz任务
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 13-12-20  下午1:02
 */
public class TestJob implements StatefulJob {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("quartz test !");
    }
}

(3)quartz任务调度测试类QuartzTest.java

package com.mcc.core.test;

import com.mcc.core.quartz.ScheduleService;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

import java.text.ParseException;

/**
 * quartz任务调度测试
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 13-12-20  下午12:49
 */
public class QuartzTest extends ScheduleService {
    @Override
    public void addScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void execute(){
        // 设置调度器
        try {
            addScheduler(StdSchedulerFactory.getDefaultScheduler());
            try {
                //可以一次执行多个addJob
                this.addJob(TestJob.class,"test","0/2 * * * * ?");
                this.start();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]){
              new QuartzTest().execute();
    }
}


第2章:java自带任务调度类

第0节:串行任务调度Timer

(1)简介

1)使用 Timer 实现任务调度的核心类是 Timer 和 TimerTask。其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的 run 方法,然后将其丢给 Timer 去执行即可。

2)Timer 的设计核心是一个 TaskList 和一个 TaskThread。Timer 将接收到的任务丢到自己的 TaskList 中,TaskList 按照 Task 的最初执行时间进行排序。TimerThread 在创建 Timer 时会启动成为一个守护线程。这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。

3)Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

(2)实例

package com.mcc.core.test;

import java.util.Timer;
import java.util.TimerTask;

/**
 * 串行作业调度Timer测试类
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-12  下午4:52
 */
public class TimerTest extends TimerTask {
    private String jobName = "";

    public TimerTest(String jobName) {
        super();
        this.jobName = jobName;
    }

    @Override
    public void run() {
        System.out.println("运行作业: " + jobName + ",开始");
        try {
            TimeUnit.MILLISECONDS.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("运行作业: " + jobName + ",完成");
    }

    public static void main(String args[]){
        Timer timer = new Timer();
        // 从现在开始 5 秒钟之后,每隔 1 秒钟执行一次 job1
        timer.schedule(new TimerTest("job1"), 5000, 1000);
        // 从现在开始 1 秒钟之后,每隔 2 秒钟执行一次 job2
        timer.schedule(new TimerTest("job2"), 1000, 2000);
    }
}


第1节:并发作业调度ScheduledExecutor

(1)简介

1)Java 5 推出了基于线程池设计的 ScheduledExecutor。其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。

2)ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。

ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …;

ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。

由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。

(2)实例

package com.mcc.core.test;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 并发任务调度ScheduledExecutor测试类
 *
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-12  下午5:05
 */
public class ScheduledExecutorTest implements Runnable{

    private String jobName = "";

    public ScheduledExecutorTest(String jobName) {
        super();
        this.jobName = jobName;
    }

    @Override
    public void run() {
        System.out.println("运行作业: " + jobName + ",开始");
        try {
            TimeUnit.MILLISECONDS.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("运行作业: " + jobName + ",完成");
    }


    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(3);

        long initialDelay1 = 1;
        long period1 = 1;
        // 从现在开始1秒钟之后,每隔1秒钟执行一次job1 ,固定时间模式
        service.scheduleAtFixedRate(
                new ScheduledExecutorTest("job1"),
                initialDelay1,period1, TimeUnit.SECONDS);

        long initialDelay2 = 2;
        long delay2 = 2;
        // 从现在开始2秒钟之后,每隔2秒钟执行一次job2  ,不固定时间模式
        service.scheduleWithFixedDelay(
                new ScheduledExecutorTest("job2"),
                initialDelay2,delay2, TimeUnit.SECONDS);
    }
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章