任务调度 Quartz

一、 Quartz 的原理:

Quartz 设计的核心类包括Scheduler(调度器), Job (任务)以及 Trigger(触发器)。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二者组装在一起,并触发任务开始执行。

二、 Quartz 的优点:

1、job 与 Trigger 的松耦合同一个 Job 可以绑定多个不同的 Trigger,同一个Trigger不可以绑定多个job;可以修改或者替换Trigger,而不用重新定义与之关联的Job,灵活性很强。

2、提供了 listener 的功能:主要包含三种 listener:JobListener,TriggerListener 以及 SchedulerListener。当系统发生故障,相关人员需要被通知时,Listener 便能发挥它的作用。最常见的情况是,当任务被执行时,系统发生故障,Listener 监听到错误,立即发送邮件给管理员

3、持久化:即将任务调度的相关数据保存下来。默认情况 下,Quartz 采用的是 org.quartz.simpl.RAMJobStore,在这种情况下,数据仅能保存在内存中,系统重启后会全部丢失。若想持久化数据,需要采用 org.quartz.simpl.JDBCJobStoreTX。

三、 Quartz 下载、安装、配置:

1、下载quartz 2.2.3.tar.gz:http://d2zwv9pap9ylyd.cloudfront.net/quartz-2.2.3-distribution.tar.gz

2、jar包引入

a、maven项目引:

<!-- quartz 任务调度 -->
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.2.3</version>
</dependency>
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz-jobs</artifactId>
	<version>2.2.3</version>
</dependency>
b、普通项目: 如果你希望在很多应用中使用quartz,将quartz的jar包放在应用服务器的classpath下即可。如果你只是希望在独立的应用中使用quartz,将quartz的jar包和你的应用依赖的其它jar包放在一起即可。
四、 Quartz 相关类介绍:

1、Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中;
2、Trigger:是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。SimpleTrigger:当仅需触发一次或者以固定时间间隔周期执行;CronTrigger:可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等;

3、Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。

4、JobDetail:Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。

5、Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。

6、ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。

五、 Quartz 的使用:

import static org.quartz.DateBuilder.futureDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.JobKey.jobKey;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import java.util.Date;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzController implements Job {

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        System.out.println("yyx's jobTest:Description=" + arg0.getJobDetail().getKey() + ",type=" + arg0.getJobDetail().getJobDataMap().get("type"));
        System.out.println(new Date());
    }

    public static void main(String[] args) {
        try {
            // 创建调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();//调度开启
            // 创建该Job负责定义需要执行任务
            JobDetail job1 = newJob(QuartzController.class).withIdentity("job1", "group1").usingJobData("type", "yyx1").build();
            // 创建触发器立即执行 默认执行一次
            SimpleTrigger trigger1 = (SimpleTrigger) newTrigger().withIdentity("myTrigger1", "group1").startNow().build();
            Date df = scheduler.scheduleJob(job1, trigger1);// 执行一次

            // 立即执行 5s一次执行5次
            JobDetail job2 = newJob(QuartzController.class).withIdentity("job2", "group1").usingJobData("type", "yyx2").build();
            SimpleTrigger trigger2 = newTrigger().withIdentity("myTrigger2", "group2").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).withRepeatCount(5)).build();
            df = scheduler.scheduleJob(job2, trigger2);

            // 给触发器绑定任务forJob(job3)
            JobDetail job3 = newJob(QuartzController.class).withIdentity("job3", "group1").usingJobData("type", "yyx3").build();
            SimpleTrigger trigger3 = newTrigger().withIdentity("myTrigger3", "group3").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).withRepeatCount(5)).forJob(job3).build();
            df = scheduler.scheduleJob(job3, trigger3);

            // 设定5分钟后运行futureDate(5, IntervalUnit.MINUTE)
            JobDetail job4 = newJob(QuartzController.class).withIdentity("job4", "group1").usingJobData("type", "yyx4").build();
            SimpleTrigger trigger4 = (SimpleTrigger) newTrigger().withIdentity("trigger4", "group4").startAt(futureDate(5, IntervalUnit.MINUTE)).build();
            df = scheduler.scheduleJob(job4, trigger4);

            // 一直执行repeatForever()
            JobDetail job5 = newJob(QuartzController.class).withIdentity("job5", "group1").usingJobData("type", "yyx5").build();
            SimpleTrigger trigger5 = newTrigger().withIdentity("myTrigger5", "group5").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();
            df = scheduler.scheduleJob(job5, trigger5);

            // 手动触发 storeDurably:是否有触发器
            JobDetail job6 = newJob(QuartzController.class).withIdentity("job6", "group1").storeDurably().build();
            scheduler.addJob(job6, true);
            scheduler.triggerJob(jobKey("job6", "group1"));

            try {
                Thread.sleep(5 * 60 * 1000);// 等待5分钟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            scheduler.shutdown();// 关闭调度
            SchedulerMetaData meta = scheduler.getMetaData();
            System.out.println("已经执行的job个数:" + meta.getNumberOfJobsExecuted());
        } catch (SchedulerException e) {
            e.printStackTrace();
        }    
    }
}

注意:同一个Trigger不可以绑定多个job,如下代码运行时会报下面的错误。

try {
                scheduler.scheduleJob(job1, trigger1);
                Thread.sleep(2 * 1000);
                scheduler.scheduleJob(job2, trigger1);
                Thread.sleep(2 * 1000);
                scheduler.scheduleJob(job3, trigger1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


参考文献:

1、http://www.quartz-scheduler.org/documentation/quartz-2.2.x/quick-start.html

2、http://ifeve.com/quartz-tutorial-job-jobdetail/

3、http://7-sun.com/doc/quartz1.8/org/quartz/package-summary.html


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值