Quartz
Peng's Blog 只记录和技术相关的东西

Quartz

2017-07-29

简介

主要用于任务调度。优于Timer和ScheduledExecutor。

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

亮点,这是Spring默认的调度框架。

特点:

  • 强大的调度功能,支持丰富多样的调度方法,满足很多需求;
  • 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
  • 分布式和集群能力。


开发环境的搭建

首先,因为这个是别的公司开发的,在jdk里面当然是没有的。所以我们需要先搭建开发环境。

如果是maven项目,在pom.xml里面添加:

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

如果是gradle项目的话,在build.gradle里面加上点东西就OK

如果是普通的项目的话需要下载jar包:

下载地址:http://download.csdn.net/detail/yxue1118/7989923


组成

job

任务,即被调度的任务

trigger

触发器,设置调度策略,定义任务调度的时间规则

scheduler

任务调度器,将job和trigger组合在一起,并触发任务开始执行

listener

当系统发生故障,相关人员需要被通知的时候就需要这个了。主要是用于监听任务。


Demo

做到定时执行一项任务。

public class QuartzTest implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Generating report - "
                + jobExecutionContext.getJobDetail().getFullName() + ", type ="
                + jobExecutionContext.getJobDetail().getJobDataMap().get("type"));
        System.out.println(new Date().toString());
    }

    public static void main(String[] args) {
        try {
            // 创建一个Scheduler
            SchedulerFactory schedFact = new StdSchedulerFactory();
            Scheduler sched = schedFact.getScheduler();
            sched.start();
            // 创建一个JobDetail,指明name,groupname,以及具体的Job类名,
            //该Job负责定义需要执行任务
            JobDetail jobDetail = new JobDetail("myJob", "myJobGroup", QuartzTest.class);
            jobDetail.getJobDataMap().put("type", "FULL");
            // 创建一个每周触发的Trigger,指明星期几几点几分执行
            Trigger trigger = TriggerUtils.makeWeeklyTrigger(3, 16, 38);
            trigger.setGroup("myTriggerGroup");
            // 从当前时间的下一秒开始执行
            trigger.setStartTime(TriggerUtils.getEvenSecondDate(new Date()));
            // 指明trigger的name
            trigger.setName("myTrigger");
            // 用scheduler将JobDetail与Trigger关联在一起,开始调度任务
            sched.scheduleJob(jobDetail, trigger);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

说明:

  • job类需要实现Job接口里面的execute方法

  • trigger用的是TriggerUtils工具类设置时间,这个非常方便

  • 创建任务调度器scheduler:

    SchedulerFactory schedFact = new StdSchedulerFactory();
    Scheduler sched = schedFact.getScheduler();
    sched.start();

  • 调度任务:sched.scheduleJob(jobDetail, trigger);


基本实现原理

核心元素

Quartz 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任务调度的元数据, scheduler 是实际执行调度的控制器。

trigger是用于定义调度时间的元素,即按照什么时间规则去执行任务。主要有四种类型:SimpleTrigger、CRonTrigger、DateIntervalTrigger、NthIncludedDayTrigger。

job表示被调度的任务。主要有两种类型:无状态的(stateless)、有状态的(stateful)。对于同一个Trigger来说,有状态的job不能被并行执行。Job 主要有两种属性:volatility 和 durability,其中 volatility 表示任务是否被持久化到数据库存储,而 durability 表示在没有 trigger 关联的时候任务是否被保留。两者都是在值为 true 的时候任务被持久化或保留。一个 job 可以被多个 trigger 关联,但是一个 trigger 只能关联一个 job。

scheduler表示任务调度器。由scheduler工厂创建。工厂的话也有两种:DirectSchedulerFactory 和 StdSchedulerFactory。 第二种工厂 StdSchedulerFactory 使用较多,因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。cheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。最常用的是StdScheduler。

核心元素关系图:

Quartz.jpg


数据存储

Quartz中的Trigger和job只有存储下来才能被使用。主要有两种存储方式:RAMJobStore, JobStoreSupport,其中 RAMJobStore 是将 trigger 和 job 存储在内存中,而 JobStoreSupport 是基于 jdbc 将 trigger 和 job 存储到数据库中。

在 Quartz 中,JobStoreSupport 使用一个驱动代理来操作 trigger 和 job 的数据存储:StdJDBCDelegate。


企业级开发

如何选择Trigger的类型

  • SimpleTrigger一般用于实现每隔一定时间执行的任务,以及重复多少次;
  • CronTirgger 类似于 LINUX 上的任务调度命令 crontab,即利用一个包含 7 个字段的表达式来表示时间调度方式。对于涉及到星期和月份的,CronTrigger是最合适的;
  • DateIntervalTrigger,适合调度类似每 N(1, 2, 3…)小时,每 N 天,每 N 周等的任务;
  • NthIncludedDayTrigger,用于每隔一个周期的第几天调度任务,例如,每个月的第 3 天执行指定的任务。

使用有状态的还是无状态的job

无状态的任务一般指的是可以并发的任务,即任务之间是相互独立的,不会互相干扰。

有状态的,一般的应用场景是:某些任务需要等前面那个任务先执行完。比如对数据库的增删改查等。

如何设置线程池和并发任务

自带的简单线程池:SimpleThreadPool。Quartz 提供了一个配置参数:org.quartz.threadPool.threadCount,可以修改。


参考资料

1、百度百科关于Quartz的介绍。https://baike.baidu.com/item/quartz/3643055?fr=aladdin

2、《几种任务调度的 Java 实现方法与比较》。2011.9。https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/index.html

3、《基于 Quartz 开发企业级任务调度应用》。2013.5。https://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/index.html


Similar Posts

上一篇 Java8-时间类

Comments

评论功能暂停使用,如需跟作者讨论请联系底部的GitHub