目录

简介

Quartz是什么?

Quartz是一个特性丰富的、开源的作业调度框架。它可以集成到任何Java应用。

使用它,你可以非常轻松的实现定时任务的调度执行。

Quartz的应用场景

场景1:提醒和告警

场景2:监听事务

场景3:定时作业

Quartz的安装

安装

1.可以直接在官网:http://www.quartz-scheduler.org/ 下载jar包。

2.如果使用maven,可以在pom.xml中添加以下依赖jar包:

<dependency>

<groupId>org.quartz-scheduler</groupId>

<artifactId>quartz</artifactId>

<version>2.2.1</version>

</dependency>

<dependency>

<groupId>org.quartz-scheduler</groupId>

<artifactId>quartz-jobs</artifactId>

<version>2.2.1</version>

</dependency>

源码

Github地址:https://github.com/quartz-scheduler/quartz

Hello World范例

开始学习之前,惯例还是show一下Hello World。

例:

1.先定义一个Job

import java.util.Date;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

public class HelloJob implements Job {

@Override

public void execute(JobExecutionContext context) throws JobExecutionException {

System.out.println(String.format("Hello World! Time:%s", new Date()));

}

}

2.定义Job和Trigger去调度我们定义的HelloJob。

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.Scheduler;

import org.quartz.SchedulerFactory;

import org.quartz.SimpleScheduleBuilder;

import org.quartz.Trigger;

import org.quartz.TriggerBuilder;

import org.quartz.impl.StdSchedulerFactory;

import org.zp.tent.scheduler.demo.job.HelloJob;

/**

@Title HelloQuartz

@Description Quartz的Hello World实例

@Author zhangpeng

@Date 2016年7月6日

*/

public class HelloWorldDemo {

public static void main(String[] args) {

try {

// 通过schedulerFactory获取一个调度器

SchedulerFactory schedulerfactory = new StdSchedulerFactory();

// 通过schedulerFactory获取一个调度器

Scheduler scheduler = schedulerfactory.getScheduler();

// 创建jobDetail实例,绑定Job实现类

JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "jobGroup1").build();

// 定义调度触发规则,本例中使用SimpleScheduleBuilder创建了一个5s执行一次的触发器

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "triggerGroup1").startNow()

.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())

.build();

// 把作业和触发器注册到任务调度中

scheduler.scheduleJob(jobDetail, trigger);

// 启动调度

scheduler.start();

// 60s后关闭

Thread.sleep(1000 * 30);

scheduler.shutdown();

System.out.println("调度任务结束");

catch (Exception e) {

e.printStackTrace();

}

}

}

好了,运行一下试试吧。

API

核心API

Scheduler接口:

作用:Scheduler接口是Quartz最核心的接口。Scheduler维护着JobDetailTrigger的注册信息。一旦注册成功,Scheduler负责执行和Job关联的触发器。

一个Scheduler实例可以视为一个调度作业容器。可以通过startshutdown方法来控制它的生命周期。

例:

// 通过schedulerFactory获取一个调度器

SchedulerFactory schedulerfactory = new StdSchedulerFactory();

// 通过schedulerFactory获取一个调度器

Scheduler scheduler = schedulerfactory.getScheduler();

// 启动

scheduler.start();

//关闭

scheduler.shutdown();

Job接口

作用:开发者实现该接口定义需要执行的作业。JobExecutionContext类提供调度上下文的各种信息。

实现Job接口的类还可以使用注解进行修饰。

@DisallowConcurrentExecution:此注解表示不允许这个Job并发执行

@PersistJobDataAfterExecution:此注解表示当这个Job的execute方法执行成功后,更新并存储它所持有的JobDetail属性中JobDataMap。如果使用这个注解,强烈建议也使用@DisallowConcurrentExecution,因为并发执行过程中,JobDataMap有可能会发生冲突。

例:

public class xxxJob implements Job {

@Override

public void execute(JobExecutionContext context) throws JobExecutionException {

}

}

JobDetail接口

作用:用于定义Job实例。

JobDetail有两个boolean属性。

isDurable:如果设为false,则对应的Job一旦没有关联的触发器,就会被Scheduler自动删除。

requestsRecovery:如果设为true,当Job执行中遇到硬中断(例如运行崩溃、机器断电等),Scheduler会重新执行。这种情况下,JobExecutionContext.isRecovering()会返回ture。

JobBuilder类

作用:用于定义、构建JobDetail实例。

例:

// 创建jobDetail实例,绑定Job实现类

JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "jobGroup1").build();

Trigger接口

作用:定义Job执行的触发规则。

Quartz中有多种触发器,最常用的是SimpleTrigger 和 CronTrigger

SimpleTrigger一般用于只执行一次或在指定时间执行的作业;CronTrigger一般用于周期性执行(例如,每日执行、每周执行)的作业,需要按照指定的时间表达式规则设置调度时间。

Priority:这个属性表示Trigger的权重。当两个Trigger触发时间相同时,权重大的那个先执行。Quartz默认的权重值为5。

Misfire Instruction:在Trigger接口中可以设置错过触发处理机制。就是说在指定触发的时间点由于某种原因错过执行的时机了,这时如何去处理。Quartz提供了多种策略,这里不详述,有兴趣的可以参考官方文档。

Job和Trigger的关系

多个Job可以依赖于一个Trigger;多个Trigger也可以关联一个Job。

但是,从最佳实践来看,最好让Job和Trigger保持一对多的关系,这样更便于管理。

TriggerBuilder类

作用:用于定义、构建Trigger实例。

例:

下面两种方式是一样的效果,都是创建一个每5s执行一次的触发器

// 定义调度触发规则, SimpleScheduleBuilder方式

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","triggerGroup1").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

// 定义调度触发规则, CronScheduleBuilder方式

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","triggerGroup1").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

第二种触发器构建方式中使用了形如"0/5 * * * * ?"的CronExpression表达式来创建触发器规则。这里不在细说,在下文的CronExpression表达式一节再详述。

JobDataMap

JobDetail接口中持有JobDataMap类。开发者可以将作业执行时需要的参数或对象填入这个类中。

填入数据和获取数据的方式很类似Json。

例:

先定义一个Job

public class WithJobDataMapJob implements Job {

public void execute(JobExecutionContext context) throws JobExecutionException {

// 基本信息

JobKey jobKey = context.getJobDetail().getKey();

TriggerKey triggerKey = context.getTrigger().getKey();

// 获取JobDataMap的方式:如果是基本类型,JobDataMap提供了多种get方法;如果是引用类型,可以直接get,然后进行强制转换

JobDataMap dataMap = context.getJobDetail().getJobDataMap();

Student student = (Student) dataMap.get("student");

List<String> interests = (List<String>) dataMap.get("interests");

String word = dataMap.getString("word");

System.out.println(String.format("[JobKey:%s][TriggerKey:%s] of DumbJob print info:", jobKey,triggerKey));

System.out.println(String.format("[Student]name:%s, age:%d, sex:%s", student.getName(),student.getAge(),

student.getSex()));

StringBuilder interestsStr = new StringBuilder();

for (String item : interests) {

interestsStr.append(item + " ");

}

System.out.println("His interests ars: " + interestsStr.toString());

System.out.println("He want to say: " + word);

System.out.println("===================================");

}

}

客户端代码:

public static void main(String[] args) {

try {

// 通过schedulerFactory获取一个调度器

SchedulerFactory schedulerfactory = new StdSchedulerFactory();

// 通过schedulerFactory获取一个调度器

Scheduler scheduler = schedulerfactory.getScheduler();

// 创建jobDetail实例,绑定Job实现类

JobDetail jobDetail = JobBuilder.newJob(WithJobDataMapJob.class).withIdentity("myJob","group1").build();

// 使用JobDataMap填入想要携带的特殊信息。可以填入基本数据类型、字符串、集合,甚至是一个对象。填入方式很类似JSON

Student student = new Student("Jack", 20, "male");

List<String> interests = new ArrayList<String>();

interests.add("dancing");

interests.add("singing");

interests.add("swimming");

String word = "Hello World!";

JobDataMap map = jobDetail.getJobDataMap();

map.put("student", student);

map.put("interests", interests);

map.put("word", word);

// 定义调度触发规则,本例中使用SimpleScheduleBuilder创建了一个5s执行一次的触发器

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "triggerGroup1").startNow()

.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())

.build();

// 把作业和触发器注册到任务调度中

scheduler.scheduleJob(jobDetail, trigger);

// 启动调度

scheduler.start();

// 60s后关闭

Thread.sleep(1000 * 30);

scheduler.shutdown();

System.out.println("调度任务结束");

catch (Exception e) {

e.printStackTrace();

}

}

其他常见API

JobKey 和 TriggerKey

在Quartz中,可以分别通过JobKey和TriggerKey来唯一地识别一个Job或一个Trigger。

这两个Key都有两个关键属性:name和group。

CronExpression表达式

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","triggerGroup1").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

还记得上文中展示的使用CronScheduleBuilder方式构建触发器时的例子吗?在这个例子中,我们使用的表达式字符串"0/5 * * * * ?"是什么意思呢?阅读本节后,你就会了解了。

表达式规则

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。

CronTrigger配置完整格式为: [秒] [分] [小时] [日] [月] [周] [年]

参数设置规则见下表

字段    

允许值

允许的特殊字符

0-59

, - * /

0-59

, - * /

小时

0-23

, - * /

日期

1-31

, - * ? / L W

月份

1-12 或者 JAN-DEC

, - * /

星期

1-7 或者 SUN-SAT

, - * ? / L #

年(可选)

留空, 1970-2099

, - * /

 cronExpression表达式参数

符号说明

通配符*

表示所有值。

例如:在分的字段上设置 "*",表示每一分钟都会触发。

通配符?

表示不指定值。使用的场景为不需要关心当前设置这个字段的值。

例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为"?" 具体设置为 0 0 0 10 * ?

通配符-

表示区间。

例如在小时上设置 "10-12",表示 10,11,12点都会触发。

通配符,

表示指定多个值。

例如在周字段上设置 "MON,WED,FRI" 表示周一,周三和周五触发

通配符/

用于递增触发。如在秒上面设置"5/15" 表示从5秒开始,每增15秒触发(5,20,35,50)。在月字段上设置'1/3'所示每月1号开始,每隔三天触发一次。

通配符L

表示最后的意思。

例如在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于"7"或"SAT"。如果在"L"前加上数字,则表示该数据的最后一个。例如在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五"

通配符W

表示离指定日期的最近那个工作日(周一至周五)。

例如在日字段上设置"15W",表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发。如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 "1W",它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,"W"前只能设置具体的数字,不允许区间"-")。

小提示:'L'和 'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同。

通配符#

表示每月的第几个周几。

例如在周字段上设置"6#3"表示在每月的第三个周六。注意如果指定"#5",正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了)。

注:表中月份一行的JAN-DEC,是指一月到十二月的英文缩写;星期一行的SUN-SAT,是指星期天到星期六的英文缩写。

使用表达式的案例

案例

意义

"0 0 12 * * ?"

每天中午12点触发

"0 15 10 ? * *"

每天上午10:15触发

"0 15 10 * * ?"

每天上午10:15触发

"0 15 10 * * ? *"

每天上午10:15触发

"0 15 10 * * ? 2005"

2005年的每天上午10:15 触发

"0 * 14 * * ?"

在每天下午2点到下午2:59期间的每1分钟触发

"0 0/5 14 * * ?"

在每天下午2点到下午2:55期间的每5分钟触发

"0 0/5 14,18 * * ?"

在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

"0 0-5 14 * * ?"

在每天下午2点到下午2:05期间的每1分钟触发

"0 10,44 14 ? 3 WED"

每年三月的星期三的下午2:10和2:44触发

"0 15 10 ? * MON-FRI"

周一至周五的上午10:15触发

"0 15 10 15 * ?"

每月15日上午10:15触发

"0 15 10 L * ?"

每月最后一日的上午10:15触发

"0 15 10 ? * 6L"

每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6L 2002-2005"

2002年至2005年的每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6#3"

每月的第三个星期五上午10:15触发

参考资料

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

官方2.2版本教程:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/

http://www.cnblogs.com/jingmoxukong/p/5647869.html

quartz.net 学习的更多相关文章

  1. Quartz定时任务学习(二)web应用/Quartz定时任务学习(三)属性文件和jar

    web中使用Quartz 1.首先在web.xml文件中加入 如下内容(根据自己情况设定) 在web.xml中添加QuartzInitializerServlet,Quartz为能够在web应用中使用 ...

  2. Quartz定时任务学习(二)web应用

    web中使用Quartz 1.首先在web.xml文件中加入 如下内容(根据自己情况设定) 在web.xml中添加QuartzInitializerServlet,Quartz为能够在web应用中使用 ...

  3. Quartz.NET学习系列

    Quartz.NET它是一个开源的任务调度引擎,对于周期性任务,持久性任务提供了很好的支持,并且支持持久性.集群等功能. 这是什么对我来说Quartz.NET学习记录: 源代码下载http://yun ...

  4. Quartz框架学习(1)—核心层次结构

    Quartz框架学习 Quartz(任务调度)框架的核心组件: job:任务.即任务调度行为中所要调度的对象. trigger:触发器.是什么促使了一个任务的调度?当然是时间.这也算事件驱动类型程序. ...

  5. Quartz定时任务学习(一)简单任务

    学习quartz首先了解三个概念: 调度器:负责调度作业和触发器: 触发器:设置作业执行的时间.参数.条件等:(简单触发器和Cron触发器) 作业:定时任务内容,被执行的程序: 下载必要的jar包,直 ...

  6. Quartz定时任务学习(五)触发器

    顾名思义,Trigger(触发器)的责任就是触发一个 Job 去执行.当用 Scheduler 注册一个 Job 的时候要创建一个 Trigger 与这个 Job 相关联.Quartz 提供了四种类型 ...

  7. Quartz.Net 学习之路02 初探Quartz.Net

    第二讲:简单的实例,看看Quartz.Net强在哪里? 直接上代码,代码里有注释: using System; using Quartz; using Quartz.Impl; namespace L ...

  8. quartz的学习和简单使用

    以前在框架中使用过,很多都是纯粹的复制粘贴,了解过用法知道如何配置,但时间久了就没什么印象了,现在重新捡起来,再次进行学习. quartz相关的介绍都已经很多了,我就不重复啰嗦,简单说一下个人的认识和 ...

  9. Quartz定时任务学习(九)Quartz监听器

    Quartz 提供了三种类型的监听器:监听 Job 的,监听 Trigger 的,和监听 Scheduler 自已的. 本章解释如何应用每一种类型来更好的管理你的 Quartz 应用,并获悉到什么事件 ...

随机推荐

  1. javascript中如何判断数组是数组

    if (!Array.isArray) { Array.isArray = function(arg) { return Object.prototype.toString.call(arg) === ...

  2. php 生成gif 动图,可控制每张图时间

    <?php //namespace gifCreator; /** * Create an animated GIF from multiple images */ class gifcreat ...

  3. springboot中,使用redisTemplate操作redis

    知识点: springboot中整合redis springboot中redisTemplate的使用 redis存数据时,key出现乱码问题 一:springboot中整合redis (1)pom. ...

  4. 大数据之路week03--day05(线程 I)

    真的,身体这个东西一定要爱护好,难受的时候电脑都不想去碰,尤其是胃和肾... 这两天耽误了太多时间,今天好转了立刻学习,即刻不能耽误!. 话不多说,说正事: 1.多线程(理解) (1)多线程:一个应用 ...

  5. django已经安装但是还是提示ModuleNotFoundError: No module named 'django'

    首先查看自己django版本与python版本是否一致: 如果一致.可能是django安装的位置与python导包的位置不一致. 我将之前的python2.6升级到python3.6,结果pip in ...

  6. 关于EZDML数据库表结构制作设计工具使用踩的坑

    我使用的是一款EZDML的数据库表结构制作设计工具 最开始在数据库创建数据库名为personalmall,基字符集为默认,数据库排序规则也是默认,创建完成之后 去EZDML生成SQL 点击执行sql ...

  7. Linux系统chmod 777 误操作目录权限 - 恢复方法

    小白操作Linux,手抖导致误修改了系统文件和目录权限,导致系统宕机的修复. -R / -R / test 有的是真不懂,执行了上面的第一条命令,有的是懂,但是操作太快或者粗心大意,或者有乱敲空格的恶 ...

  8. Python3基础学习-while循环实例- 猜数字游戏

    需求: 猜数字游戏, 要求如下: 给个数字, 比如是66. 让用户一直猜,直到猜对退出. 中间输入q或Q也能退出 如果猜大了,提示用户猜小一点; 如果猜小了,提示用户猜大一点; likely = 66 ...

  9. using来定义类的别名,typedef,#define

    宏定义:其实就是替换作用 #define TRUE 1    //结尾无分号,宏名TRUE,计算机会把所有TRUE替换为1. typedef:定义类的别名 tpyedef unsigned int U ...

  10. 002_linux驱动之_register_chrdev注册字符设备

    (一)解析:register_chrdev函数和unregister_chrdev函数 (二)register_chrdev函数原型 int register_chrdev(unsigned int ...