Quartz学习总结

一、基本介绍:

Quartz OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。读者可以到 http://www.quartz-scheduler.org/站点下载 Quartz 的发布版本及其源代码。

Quartz 具有以下特点:

1、强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;

2、灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;

3、分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。

这些总结起来就是:在某一个有规律的时间点干某件事。并且时间的触发的条件可以非常复杂(比如每月最后一个工作日的17:50),复杂到需要一个专门的框架来干这个事。 Quartz就是来干这样的事,你给它一个触发条件的定义,它负责到了时间点,触发相应的Job起来干活。

二、POM引用:

 1 <dependency>
 2     <groupId>org.quartz-scheduler</groupId>
 3     <artifactId>quartz</artifactId>
 4     <version>2.2.3</version>
 5 </dependency>
 6 <dependency>
 7     <groupId>org.quartz-scheduler</groupId>
 8     <artifactId>quartz-jobs</artifactId>
 9     <version>2.2.3</version>
10 </dependency>

 

三、基本结构:

(一)核心元素:

1、Scheduler:一个scheduler的生命周期是有限的,从通过SchedulerFactory创建开始直到调用它的shutdown()方法。scheduler接口一旦创建,就能添加、移除、和列出jobtrigger,并执行另一些与调度相关的操作(例如暂停trigger),然而,在schedulerstart()方法启动前,它不会作用于任何trigger(执行job)。。

2、Job: 一个job就是实现了Job接口的类。如下所示,这个接口只有一个简单的方法:execute

3、JobDetail JobDetail对象由Quartz客户端(你的程序)在job添加进scheduler的时候创建。这个对象包含了很多job的属性设置,和JobDataMap一样,它能够存储你的job实例的状态信息。JobDetail对象本质上是定义的job实例

4、Trigger

(1) trigger对象常常用于触发job的执行(或者触发),当你希望安排一个job,你可以实例化一个trigger,并调整其属性来提供你想要的调度。trigger可能有一个与它们关联的JobDataMap对象。JobDataMap用于传递特定于触发器触发的工作参数。Quartz附带一些不同的触发类型,但是最常用的就是SimpleTriggerCronTrigger

(2) SimpleTrigger很方便,如果你需要一次性执行(只是在一个给定时刻执行job),或者如果你需要一个job在一个给定的时间,并让它重复N,并在执行之间延迟T

(3) CronTrigger是有用的,如果你想拥有引发基于当前日历时间表,如每个星期五,中午或在每个月的第十天 10:15

5、JobBuilder: 用于定义/构建已经定义了Job实例的JobDetail实例。

6、TriggerBuilder: 用于定义/构建Trigger实例。

(二)数据表说明:

序号

表名

说明

1

QRTZ_CALENDARS

存储QuartzCalendar信息

2

QRTZ_CRON_TRIGGERS

存储CronTrigger,包括Cron表达式和时区信息

3

QRTZ_FIRED_TRIGGERS

存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息

4

QRTZ_PAUSED_TRIGGER_GRPS

存储已暂停的Trigger组的信息

5

QRTZ_SCHEDULER_STATE

存储少量的有关Scheduler的状态信息,和别的Scheduler实例

6

QRTZ_LOCKS

存储程序的悲观锁的信息

7

QRTZ_JOB_DETAILS

存储每一个已配置的Job的详细信息

8

QRTZ_SIMPLE_TRIGGERS

存储简单的Trigger,包括重复次数、间隔、以及已触的次数

9

QRTZ_BLOG_TRIGGERS

Trigger作为Blob类型存储

10

QRTZ_TRIGGERS

存储已配置的Trigger的信息

11

QRTZ_SIMPROP_TRIGGERS

 

 

(三)关系图:

 

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

Quartz 中,trigger 是用于定义调度时间的元素,即按照什么时间规则去执行任务。Quartz 中主要提供了四种类型的 triggerSimpleTriggerCronTirggerDateIntervalTrigger,和 NthIncludedDayTrigger。这四种 trigger 可以满足企业应用中的绝大部分需求。

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

Quartz 中, scheduler scheduler 工厂创建:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二种工厂 StdSchedulerFactory 使用较多,因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。 Scheduler 主要有三种:RemoteMBeanSchedulerRemoteScheduler StdScheduler。本文以最常用的 StdScheduler 为例讲解。这也是笔者在项目中所使用的 scheduler 类。

 

线程图:

Scheduler 调度线程主要有两个: 执行常规调度的线程,和执行 misfired trigger 的线程。常规调度线程轮询存储的所有 trigger,如果有需要触发的 trigger,即到达了下一次触发的时间,则从任务执行线程池获取一个空闲线程,执行与该 trigger 关联的任务。Misfire 线程是扫描所有的 trigger,查看是否有 misfired trigger,如果有的话根据 misfire 的策略分别处理。

(四)启动流程:

 

quartz是配置在spring中,当服务器启动时,就会装载相关的beanSchedulerFactoryBean实现了InitializingBean接口,因此在初始化bean的时候,会执行afterPropertiesSet方法,该方法将会调用SchedulerFactory(DirectSchedulerFactory 或者 StdSchedulerFactory,通常用StdSchedulerFactory)创建SchedulerSchedulerFactory在创建quartzScheduler的过程中,将会读取配置参数,初始化各个组件。

四、简单示例:

1 public class HelloJob implements Job {
2     public HelloJob() {
3     }
4  
5     public void execute(JobExecutionContext context) throws JobExecutionException {
6         System.out.println("Hello World! - " + new Date());
7     }
8 }
 1 public class SimpleExample { 
 2     public void run() throws Exception { 
 3         System.out.println("------- 初始化 ----------------------");
 4         // 首先要实例化scheduler
 5         SchedulerFactory schedulerFactory = new StdSchedulerFactory();
 6         Scheduler scheduler = schedulerFactory.getScheduler();
 7         System.out.println("------- 初始化完成 -----------");
 8  
 9         // 获取给定时间的下一个完整分钟的时间,例如给定时间 08:13:54 则会反回 08:14:00
10         Date runTime = DateBuilder.evenMinuteDate(new Date());
11  
12         System.out.println("------- Job安排 -------------------");
13         // 获取job实例
14         JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
15         // 在下一轮分钟触发运行
16         Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
17         // 告诉quartz使用某个trigger执行某个job
18         scheduler.scheduleJob(job, trigger);
19         System.out.println(job.getKey() + " 将会运行于: " + runTime);
20  
21         // 启动scheduler
22         scheduler.start();
23  
24         System.out.println("------- 开始安排 -----------------");
25         System.out.println("------- 等待65秒 -------------");
26         Thread.sleep(65L * 1000L);
27  
28         // 关闭scheduler
29         System.out.println("------- 关闭 ---------------------");
30         scheduler.shutdown(true);
31         System.out.println("------- 关闭完成 -----------------");
32     }
33  
34     public static void main(String[] args) throws Exception {
35         SimpleExample example = new SimpleExample();
36         example.run();
37     }
38

五、Spring集成:

1、新建spring工程以及maven引入quartz包;

2、application.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
 4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
 5     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 7     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
 8     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
 9     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
10 
11     <!-- 
12         Spring整合Quartz进行配置遵循下面的步骤:
13         1:定义工作任务的Job
14         2:定义触发器Trigger,并将触发器与工作任务绑定
15         3:定义调度器,并将Trigger注册到Scheduler
16      -->
17     <!-- 1:定义任务的bean ,这里使用JobDetailFactoryBean,也可以使用MethodInvokingJobDetailFactoryBean ,配置类似-->
18     <bean name="hwJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
19         <!-- 指定job的名称 -->
20         <property name="name" value="hw_job"/>
21         <!-- 指定job的分组 -->
22         <property name="group" value="hw_group"/>
23         <!-- 指定具体的job类 -->
24         <property name="jobClass" value="com.dufy.spring.quartz.chapter01.job.HelloWorldJob"/>
25         <!-- 必须设置为true,如果为false,当没有活动的触发器与之关联时会在调度器中会删除该任务  -->
26         <property name="durability" value="true"/>
27         <!-- 指定spring容器的key,如果不设定在job中的jobmap中是获取不到spring容器的 -->
28         <property name="applicationContextJobDataKey" value="applicationContext"/>
29     </bean>
30     <!-- 2.1:定义触发器的bean,定义一个Simple的Trigger,一个触发器只能和一个任务进行绑定 -->
31     <!-- <bean name="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
32         指定Trigger的名称
33         <property name="name" value="hw_trigger"/>
34         指定Trigger的名称
35         <property name="group" value="hw_trigger_group"/>
36         指定Tirgger绑定的Job
37         <property name="jobDetail" ref="hwJob"/>
38         指定Trigger的延迟时间 1s后运行
39         <property name="startDelay" value="1000"/>
40         指定Trigger的重复间隔  5s
41         <property name="repeatInterval" value="5000"/>
42         指定Trigger的重复次数
43         <property name="repeatCount" value="5"/>
44     </bean> -->
45     <!-- 2.2:定义触发器的bean,定义一个Cron的Trigger,一个触发器只能和一个任务进行绑定 -->
46     <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
47         <!-- 指定Trigger的名称 -->
48         <property name="name" value="hw_trigger"/>
49         <!-- 指定Trigger的名称 -->
50         <property name="group" value="hw_trigger_group"/>
51         <!-- 指定Tirgger绑定的Job -->
52         <property name="jobDetail" ref="hwJob"/>
53         <!-- 指定Cron 的表达式 ,当前是每隔1s运行一次 -->
54         <property name="cronExpression" value="0/1 * * * * ?" />
55     </bean>
56     <!-- 3.定义调度器,并将Trigger注册到调度器中 -->
57     <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
58         <property name="triggers">
59             <list>
60                 <!-- <ref bean="simpleTrigger"/> -->
61                 <ref bean="cronTrigger"/>
62             </list>
63         </property>
64         <!-- <property name="autoStartup" value="true" /> -->
65 </bean>
66 <!-- 持久化数据配置,需要添加quartz.properties-->
67     <bean name="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
68         <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
69         <property name="configLocation" value="classpath:quartz.properties"/>   
70     </bean>
71 </beans>

3、quartz.properties 

 1 org.quartz.scheduler.instanceName: dufy_test
 2 org.quartz.scheduler.instanceId = AUTO
 3 
 4 org.quartz.scheduler.rmi.export: false
 5 org.quartz.scheduler.rmi.proxy: false
 6 org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
 7 #============================================================================
 8 # Configure ThreadPool
 9 #============================================================================
10 org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
11 org.quartz.threadPool.threadCount: 2
12 org.quartz.threadPool.threadPriority: 5
13 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
14 
15 org.quartz.jobStore.misfireThreshold: 60000
16 #============================================================================
17 # Configure JobStore
18 #============================================================================
19 
20 #default config
21 #org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
22 #持久化配置
23 org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
24 org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
25 org.quartz.jobStore.useProperties:true
26 
27 #============================================================================
28 #havent cluster spring
29 #============================================================================
30 org.quartz.jobStore.isClustered = false  
31 
32 #数据库表前缀
33 org.quartz.jobStore.tablePrefix:qrtz_
34 org.quartz.jobStore.dataSource:qzDS
35 
36 #============================================================================
37 # Configure Datasources
38 #============================================================================
39 #JDBC驱动
40 org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
41 org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartz_test
42 org.quartz.dataSource.qzDS.user:root
43 org.quartz.dataSource.qzDS.password:root
44 org.quartz.dataSource.qzDS.maxConnection:10

4、Job类的实现: 

 1 public class HelloWorldJob implements Job{
 2 
 3     private Logger log = LoggerFactory.getLogger(this.getClass());
 4 
 5     public void execute(JobExecutionContext arg0) throws JobExecutionException {
 6         log.info("This is a first spring combine quartz !");
 7         log.info("Welcome to Spring_Quartz World!"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) );
 8         log.info("Let's begin ! \n \n");
 9     }
10 }

5、调度程序的实现: 

 1 public class HWTest {
 2     private static Scheduler scheduler;
 3     
 4     public static void main(String[] args) {
 5         ApplicationContext ac = new ClassPathXmlApplicationContext("spring_quartz.xml");
 6          scheduler = (StdScheduler)ac.getBean("scheduler");
 7          startSchedule();
 8     }
 9 
10     public static void startSchedule() {
11         try {
12             // 1、创建一个JobDetail实例,指定Quartz
13             JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class)            
14                     .withIdentity("job1_1", "jGroup1")
15                     // 任务名,任务组
16                     .build();
17             // 触发器类型
18             //SimpleScheduleBuilder builder = SimpleScheduleBuilder
19                     // 设置执行次数
20                     //.repeatSecondlyForTotalCount(5);
21             CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");
22             // 2、创建Trigger
23             Trigger trigger = TriggerBuilder.newTrigger()
24                     .withIdentity("trigger1_1", "tGroup1").startNow()
25                     .withSchedule(builder)
26                     .build();
27             // 3、创建Scheduler
28             scheduler = StdSchedulerFactory.getDefaultScheduler();
29             scheduler.start();
30             // 4、调度执行
31             scheduler.scheduleJob(jobDetail, trigger);
32         } catch (SchedulerException e) {
33             e.printStackTrace();
34         }
35     }
36 }

六、参考资料:

https://www.cnblogs.com/drift-ice/p/3817269.html

https://blog.csdn.net/lkl_csdn/article/details/73613033

https://blog.csdn.net/u010648555/article/details/53363321

https://blog.csdn.net/gjb724332682/article/details/53019953?utm_source=blogkpcl6

 

posted on 2018-10-24 16:31  小夏coding  阅读(181)  评论(0编辑  收藏  举报

导航