阅读目录

  • 简单介绍
  • 章节1:Quartz简单实例
  • 章节2:Job、JobDetail、JobBuilder
  • 章节3:Trigger、TriggerBuilder
  • 章节4:Scheduler
  • 章节5:JobListener、SchedulerListener、TriggerListener
  • 章节6:Cron表达式
  • 章节7:程序示例
  • 章节8:参考链接

简单介绍

在实际编程中,我们经常会遇到定时任务,或是隔一段时间执行指定任务,例如:
1. 在每月的30号9:00统计人员出勤情况;
2. 每隔10分钟执行一次入库操作;
上面的例子中,需要执行的操作就是Job(作业),而在指定时间或者间隔固定时间去触发这个Job的就是Trigger(触发器),而把二者联系在一起的就是Scheduler(调度器);


Quartz主要要理解三个方面:
  1. Scheduler:调度器,将Job和Trigger关联起来;
  2. Job          :需要执行的作业;
  3. Trigger    :触发器,指定执行的时间,主要包括两种方式:
<1>指定时间:如每月15号9:00,或者每天的12:00等等;
<2>间隔时间:如每隔10分钟执行一次,每隔2h执行一次等等;


回到顶部

一、Quartz简单实例

下面给出一个简单的示例:
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
 
  Scheduler sched = schedFact.getScheduler();
 
  sched.start();
 
  // define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1")
      .build();
 
  // Trigger the job to run now, and then every 40 seconds
  trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())
      .build();
 
  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

下面的截图是Java源码给出的示例:

我们在使用Quartz时,一般的操作步骤为:
步骤1:自定义Job类(如:MyJob),实现Job接口;
步骤2:使用JobBuilder生成JobDetail;
步骤3:定义Trigger类,一般使用TriggerBuilder生成;
步骤4:定义Scheduler类,使用Scheduler .scheduleJob(job, trigger)将job和trigger进行关联;
步骤5:Scheduler.start();
步骤6:当需要关闭Scheduler时,使用Scheduler.shutdown();
下面将具体进行讲解。

回到顶部

二、Job、JobDetail、JobBuilder

官方定义:
  1. Job - an interface to be implemented by components that you wish to have executed by the scheduler.
  2. JobDetail - used to define instances of Jobs.
  3. JobBuilder - used to define/build JobDetail instances, which define instances of Jobs.

Job

Job是一个接口类,下面是它的源码:
如果要实现自己的作业(任务),最简单的方式就是实现该接口,并实现接口中的execute()方法,当触发该作业时,就是执行execute()方法;
public class HelloJob implements Job {public HelloJob() {}public void execute(JobExecutionContext context)throws JobExecutionException{System.err.println("Hello!  HelloJob is executing.");}}


JobDetail

JobDetail :用于定义Job的实例,一般该类都是通过JobBuilder生成;
JobBuilder:用于定义或创建JobDetail实例,使用了建造者模式;
JobDetail job = newJob(HelloJob.class).withIdentity("myJob", "group1") // name "myJob", group "group1".build();
//带参数
JobDetail job = JobBuilder.newJob(clazz)
.withIdentity(new JobKey(jobName, groupName))
.usingJobData(new JobDataMap(params))
.build();

从上面的接口类中我们可以知道,只要有了JobDetail的实现类,我们就可以获取到:
  1. key;
  2. JobClass;
  3. JobDataMap;等
那我们在自定义的Job中怎么才能获取到JobDetail相关信息呢?

由上面可知,当自定义的作业被触发时,我们可以通过JobExecutionContext获取到JobDetail,进而获取JobDataMap、JobKey、JobClass等等信息;

JobBuilder

这里JobBuilder使用了建造者模式,下面对其源码进行解析;
对于建造者模式,这里不进行详述,首先看下它的字段:

JobKey:作业的唯一标识,由name和group组成,如下:

jobClass:指定上述我们讲的自定义的Job(如:HelloJob );

JobDataMap:可以通过这个属性给自定义的Job(如:HelloJob)传递参数;

因为使用了建造者模式,所以实际创建的对象为:JobDetailImpl
JobDetailImpl类实现了JobDeteil接口,如下:
下图是类的层级结构图:

回到顶部

三、Trigger、TriggerBuilder

官方定义:
Trigger - a component that defines the schedule upon which a given Job will be executed.
TriggerBuilder - used to define/build Trigger instances.


下面是触发器层次结构,常用的有SimpleTrigger、CronTrigger等;

SimpleTrigger

主要属性:

CronTrigger

使用CronTrigger可以进行很强大的控制,关于Cron表达式,下面的章节会介绍;
主要的参数:


TriggerBuilder

首先看下实现的例子:使用的也是建造者模式(建造者模式可自行搜索);
TriggerBuilder的属性如下:

通过withIdentity()方法设定trigger唯一标识:

通过forJob()方法将Trigger和指定的Job绑定
前面我们已经知道:
  • 在使用JobBuilder创建JobDetail时,通过方法withIdentity()指定了JobDetail的JobKey
  • 这里通过TriggerBuilder的forJob()同样指定了JobKey;
==>只要上面两个JobKey设置的相同,则JobDetail和Trigger便绑定在一起了;

后面只需要使用Scheduler.scheduleJob(job,trigger)进行调度即可;


通过方法withSchedule设置调度器:
从上面可以看出,这个方法传递进去的实际上是一个调度器Scheduler的Builder,真正的调度器Scheduler还是需要通过ScheduleBuilder去创建,这里使用的还是建造者模式,从下面的层次可以看出,已经实现了4种ScheduleBuilder,这里以SimplesCheduleBuilder进行分析,其他类似
下面我们看看SimplesCheduleBuilder的源码实现;
上面是build方法,可以看出,真正创建的是:SimpleTriggerImpl类,这个类在上面已经介绍过,它是Trigger的一个实现类;

我们接着看TriggerBuilder的build方法:
回到顶部

四、Scheduler

官方定义:
Scheduler - the main API for interacting with the scheduler.
与调度程序交互的主要API。

具体实现类:
主要的方法:

  1. Scheduler  scheduler = StdSchedulerFactory.getDefaultScheduler();
  2. scheduler.schedeleJob(Job,trigger)
  3. scheduler.start();
  4. scheduler.shutdown();
说明:

只有在scheduler.start();之后,trigger以及Job才能有效运行;
shutdown用于关闭;


schedeleJob方法介绍
// Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

官方介绍如下:
现在以StdScheduler作为示例进行介绍:


start()方法介绍
使用start()方法来激活Trigger,执行定时任务;

回到顶部

五、JobListener、SchedulerListener、TriggerListener

对监听进行注册:
      

回到顶部

六、Cron表达式

语法格式:

示例:
  • * ("all values") - used to select all values within a field. For example, "" in the minute field means *"every minute".

  • ? ("no specific value") - useful when you need to specify something in one of the two fields in which the character is allowed, but not the other. For example, if I want my trigger to fire on a particular day of the month (say, the 10th), but don't care what day of the week that happens to be, I would put "10" in the day-of-month field, and "?" in the day-of-week field. See the examples below for clarification.

  • - - used to specify ranges. For example, "10-12" in the hour field means "the hours 10, 11 and 12".

  • , - used to specify additional values. For example, "MON,WED,FRI" in the day-of-week field means "the days Monday, Wednesday, and Friday".

  • / - used to specify increments. For example, "0/15" in the seconds field means "the seconds 0, 15, 30, and 45". And "5/15" in the seconds field means "the seconds 5, 20, 35, and 50". You can also specify '/' after the '' character - in this case '' is equivalent to having '0' before the '/'. '1/3' in the day-of-month field means "fire every 3 days starting on the first day of the month".

  • L ("last") - has different meaning in each of the two fields in which it is allowed. For example, the value "L" in the day-of-month field means "the last day of the month" - day 31 for January, day 28 for February on non-leap years. If used in the day-of-week field by itself, it simply means "7" or "SAT". But if used in the day-of-week field after another value, it means "the last xxx day of the month" - for example "6L" means "the last friday of the month". You can also specify an offset from the last day of the month, such as "L-3" which would mean the third-to-last day of the calendar month. When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing/unexpected results.

  • W ("weekday") - used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month". So if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary of a month's days. The 'W' character can only be specified when the day-of-month is a single day, not a range or list of days.

The 'L' and 'W' characters can also be combined in the day-of-month field to yield 'LW', which translates to *"last weekday of the month"*.

  • # - used to specify "the nth" XXX day of the month. For example, the value of "6#3" in the day-of-week field means"the third Friday of the month" (day 6 = Friday and "#3" = the 3rd one in the month). Other examples: "2#1" = the first Monday of the month and "4#5" = the fifth Wednesday of the month. Note that if you specify "#5" and there is not 5 of the given day-of-week in the month, then no firing will occur that month.
                                                                                                                                                                                                                          回到顶部

七、程序示例


AbstractSchedule类:抽象基类

  1. package com.sssppp.TimerSchedule.quartz.schedule;
  2. import java.util.Date;
  3. import java.util.Map;
  4. import java.util.Properties;
  5. import org.quartz.CronScheduleBuilder;
  6. import org.quartz.CronTrigger;
  7. import org.quartz.JobBuilder;
  8. import org.quartz.JobDataMap;
  9. import org.quartz.JobDetail;
  10. import org.quartz.JobKey;
  11. import org.quartz.Scheduler;
  12. import org.quartz.SchedulerException;
  13. import org.quartz.TriggerBuilder;
  14. import org.quartz.impl.StdSchedulerFactory;
  15. import com.sssppp.TimerSchedule.quartz.listeners.MyJobListener;
  16. import com.sssppp.TimerSchedule.quartz.listeners.MySchedulerListener;
  17. import com.sssppp.TimerSchedule.quartz.listeners.MyTriggerListener;
  18. public abstract class AbstractSchedule {
  19. public Scheduler scheduler = null;
  20. private static final String JOB_GROUPNAME = "MY_JOB_GROUP";
  21. private static final String TRIGGER_GROUPNAME = "MY_TRIGGER_GROUP";
  22. /**
  23. * 初始化Scheduler,并添加Listeners
  24. */
  25. public AbstractSchedule() {
  26. try {
  27. if (scheduler == null) {
  28. System.out.println("Begin init scheduler...");
  29. try {
  30. Properties props = new Properties();
  31. props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
  32. "org.quartz.simpl.SimpleThreadPool");
  33. props.put("org.quartz.threadPool.threadCount", "100");// 同时100个线程运行
  34. props.put("org.quartz.jobStore.misfireThreshold", "180000");// trigger过期30分钟内还有效
  35. StdSchedulerFactory factory = new StdSchedulerFactory();
  36. factory.initialize(props);
  37. scheduler = factory.getScheduler();
  38. } catch (SchedulerException e) {
  39. e.printStackTrace();
  40. }
  41. scheduler.getListenerManager().addJobListener(new MyJobListener());
  42. scheduler.getListenerManager().addSchedulerListener(
  43. new MySchedulerListener());
  44. scheduler.getListenerManager().addTriggerListener(
  45. new MyTriggerListener());
  46. }
  47. } catch (Exception e) {
  48. System.err.println("Init scheduler failed, error message :" + e);
  49. }
  50. }
  51. public abstract Scheduler handleJob(String jobName, String triggerName,
  52. String cronStr);
  53. @SuppressWarnings({ "unchecked", "rawtypes" })
  54. public void scheduleJob(String jobName, String triggerName, String express,
  55. Class clazz) {
  56. JobDetail job = null;
  57. CronTrigger trigger = null;
  58. try {
  59. job = JobBuilder.newJob(clazz).withIdentity(jobName, JOB_GROUPNAME)
  60. .build();
  61. trigger = TriggerBuilder.newTrigger()
  62. .withIdentity(triggerName, TRIGGER_GROUPNAME)
  63. .forJob(jobName, JOB_GROUPNAME)
  64. .withSchedule(CronScheduleBuilder.cronSchedule(express))
  65. .build();
  66. } catch (Exception e) {
  67. System.err.println("scheduler ParseException!" + e);
  68. }
  69. Date date = null;
  70. try {
  71. date = scheduler.scheduleJob(job, trigger);
  72. } catch (SchedulerException e) {
  73. System.err.println("scheduler SchedulerException!" + e);
  74. }
  75. System.out.println(job.getKey().toString()
  76. + " has been scheduled to run at: " + date
  77. + " and repeat based on expression: "
  78. + trigger.getCronExpression());
  79. }
  80. /**
  81. * 创建Job和Trigger,并使用scheduler将job和Trigger进行关联
  82. *
  83. * @param jobName
  84. * @param triggerName
  85. * @param express
  86. * :cronStr表达式
  87. * @param clazz
  88. * :job的class
  89. * @param params
  90. * :Job使用的参数
  91. */
  92. @SuppressWarnings({ "unchecked", "rawtypes" })
  93. public void scheduleJobWithParams(String jobName, String triggerName,
  94. String express, Class clazz, Map<String, Object> params) {
  95. JobDetail job = null;
  96. CronTrigger trigger = null;
  97. try {
  98. job = JobBuilder.newJob(clazz)
  99. .withIdentity(new JobKey(jobName, JOB_GROUPNAME))
  100. .usingJobData(new JobDataMap(params)).build();
  101. trigger = TriggerBuilder.newTrigger()
  102. .withIdentity(triggerName, TRIGGER_GROUPNAME)
  103. .forJob(jobName, JOB_GROUPNAME)
  104. .withSchedule(CronScheduleBuilder.cronSchedule(express))
  105. .build();
  106. } catch (Exception e) {
  107. System.err.println("scheduler ParseException!" + e);
  108. }
  109. Date date = null;
  110. try {
  111. date = scheduler.scheduleJob(job, trigger);
  112. } catch (SchedulerException e) {
  113. System.err.println("scheduler SchedulerException!" + e);
  114. }
  115. System.out.println(job.getKey().toString()
  116. + " has been scheduled to run at: " + date
  117. + " and repeat based on expression: "
  118. + trigger.getCronExpression());
  119. }
  120. /**
  121. * Starts the Scheduler's threads that fire Triggers
  122. */
  123. public void startJob() {
  124. try {
  125. this.scheduler.start();
  126. } catch (SchedulerException e) {
  127. System.err.println("trigger job error!" + e);
  128. }
  129. }
  130. public boolean stopJob(String jobName) {
  131. boolean b = false;
  132. JobKey jobkey = new JobKey(jobName, JOB_GROUPNAME);
  133. try {
  134. if (this.scheduler.checkExists(jobkey)) {
  135. b = this.scheduler.deleteJob(jobkey);
  136. System.out.println("Stop Job[" + jobName + "] success.");
  137. }
  138. } catch (SchedulerException e) {
  139. System.err.println("Stop job fail.");
  140. e.printStackTrace();
  141. }
  142. return b;
  143. }
  144. public void shutdownScheduler() {
  145. try {
  146. this.scheduler.shutdown(true);
  147. System.out.println("Shutdown scheduler success.");
  148. } catch (SchedulerException e) {
  149. System.err.println("Shutdown Scheduler fail.");
  150. e.printStackTrace();
  151. }
  152. }
  153. }

MyJobSchedule.java

  1. package com.sssppp.TimerSchedule.quartz.schedule;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import org.quartz.Scheduler;
  5. import com.sssppp.TimerSchedule.quartz.Jobs.MyJob;
  6. public class MyJobSchedule extends AbstractSchedule {
  7. private static MyJobSchedule myJobSchedule = new MyJobSchedule();
  8. private MyJobSchedule() {
  9. }
  10. public static MyJobSchedule getInstance() {
  11. return myJobSchedule;
  12. }
  13. @Override
  14. public Scheduler handleJob(String jobName, String triggerName,
  15. String cronStr) {
  16. Map<String, Object> params = new HashMap<String, Object>();
  17. params.put(MyJob.JOB_PARAM_KEY, "This is myJob param");
  18. scheduleJobWithParams(jobName, triggerName, cronStr, MyJob.class, params);
  19. startJob();
  20. return this.scheduler;
  21. }
  22. }

MyJob.java

  1. package com.sssppp.TimerSchedule.quartz.Jobs;
  2. import java.util.Date;
  3. import org.quartz.Job;
  4. import org.quartz.JobExecutionContext;
  5. import org.quartz.JobExecutionException;
  6. import com.ibm.icu.text.SimpleDateFormat;
  7. public class MyJob implements Job {
  8. public final static String JOB_PARAM_KEY = "jobParam";
  9. @Override
  10. public void execute(JobExecutionContext jobexecutioncontext)
  11. throws JobExecutionException {
  12. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  13. // 获取传递给Job的参数
  14. String param = (String) jobexecutioncontext.getJobDetail()
  15. .getJobDataMap().get(JOB_PARAM_KEY);
  16. System.out.println("Now exec MyJob,param【" + param + "】, time:"
  17. + sdf.format(new Date()));
  18. }
  19. }

QuartzManager.java

  1. package com.sssppp.TimerSchedule.quartz;
  2. import com.sssppp.TimerSchedule.quartz.schedule.MyJobSchedule;
  3. public class QuartzManager {
  4. private static final QuartzManager quartzManager = new QuartzManager();
  5. private static final String MY_JOB_NAME = "MY_JOB_NAME";
  6. private static final String MY_TRIGGER_NAME = "MY_TRIGGER_NAME";
  7. private static final String MY_JOB_CRONSTR = "0/5 * * * * ?";
  8. private QuartzManager() {
  9. }
  10. public static QuartzManager getInstance() {
  11. return quartzManager;
  12. }
  13. public void startMyJob() {
  14. MyJobSchedule.getInstance().handleJob(MY_JOB_NAME, MY_TRIGGER_NAME,
  15. MY_JOB_CRONSTR);
  16. }
  17. public void stopMyJobAndShutdownScheduler() {
  18. MyJobSchedule.getInstance().stopJob(MY_JOB_NAME);
  19. MyJobSchedule.getInstance().shutdownScheduler();
  20. }
  21. }


TestCase.java

  1. package com.sssppp.TimerSchedule.quartz;
  2. public class TestCase {
  3. @SuppressWarnings("static-access")
  4. public static void main(String[] args) throws InterruptedException {
  5. QuartzManager.getInstance().startMyJob();
  6. Thread.currentThread().sleep(12 * 1000);
  7. QuartzManager.getInstance().stopMyJobAndShutdownScheduler();
  8. }
  9. }

回到顶部

八、参考链接

http://www.cnblogs.com/ssslinppp 
http://www.quartz-scheduler.org/
http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger 

来自为知笔记(Wiz)

附件列表

  • 1.png
  • 1_2.png
  • 1_3.png
  • 2.png
  • 3.png
  • a2.png

转载于:https://www.cnblogs.com/ssslinppp/p/5055524.html

【原创】Quartz代码详解相关推荐

  1. socket 获取回传信息_Luat系列官方教程5:Socket代码详解

    文章篇幅较长,代码部分建议横屏查看,或在PC端打开本文链接.文末依然为爱学习的你准备了专属福利~ TCP和UDP除了在Lua代码声明时有一些不同,其他地方完全一样,所以下面的代码将以TCP长连接的数据 ...

  2. android生命周期_Android开发 View的生命周期结合代码详解

    咱们以TextView控件为例: /** * Created by SunshineBoy on 2020/9/23. */ public class TestTextView extends and ...

  3. Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108022984 各位读者,知识无穷而人力有穷 ...

  4. Qt开发技术:Q3D图表开发笔记(二):Q3DBar三维柱状图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130150728 各位读者,知识无穷而人力有穷,要么改需 ...

  5. Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130264470 各位读者,知识无穷而人力有穷,要么改需 ...

  6. Quartz.Net详解

    Quartz.Net详解 代码仓库地址 Gitee:https://gitee.com/bluecusliyou Github:https://github.com/bluecusliyou 零.文章 ...

  7. yoloV3代码详解(注释)

    原文链接:https://www.cnblogs.com/hujinzhou/p/guobao_2020_3_13.html yolo3各部分代码详解(超详细) </h1><div ...

  8. 【CV】Pytorch一小时入门教程-代码详解

    目录 一.关键部分代码分解 1.定义网络 2.损失函数(代价函数) 3.更新权值 二.训练完整的分类器 1.数据处理 2. 训练模型(代码详解) CPU训练 GPU训练 CPU版本与GPU版本代码区别 ...

  9. html5代码转换为视频,HTML5中的视频代码详解

    摘要 腾兴网为您分享:HTML5中的视频代码详解,智学网,云闪付,易推广,小红书等软件知识,以及360win10,流量魔盒,fitbit,上港商城,安卓2.3.7,全民惠,五年级下册英语单词表图片,t ...

最新文章

  1. GSMA:中国有望成为全球领先的5G市场之一
  2. 补零对有限长序列频谱及DFT的影响
  3. 机器学习笔记: Discriminative vs Generative Models
  4. opencv 中 快速傅里叶变换 FFT
  5. 终极解密输入网址按回车到底发生了什么
  6. ASP.NET MVC 相关的社群与讨论区
  7. qt给exe文件添加图标
  8. 【Kafka】【未解决】kafka反序列化数据报错jackson2 JsonParseException: Invalid UTF-8 middle byte 0xc0
  9. windows mysql5.7 忘记密码_Windows下Mysql5.7忘记root密码的解决方法
  10. XSS-Game level 6
  11. CenOS7.4内核升级修复系统漏洞
  12. 海龟绘图两小时上手C语言 - 3 正方形螺旋线
  13. 数据结构利器之私房STL
  14. SEO HTML语义化
  15. 络达1562系统深度睡眠后RTC唤醒应用
  16. 台式计算机对比评测报告,正常台式电脑测试报告.doc
  17. Python中scipy库的pearsonr(x, y)的使用
  18. Android 快应用
  19. firewalld防火墙配置ip地址伪装和端口转发
  20. 【erlang】【rebar依赖】添加eredis依赖

热门文章

  1. access 使用dsn 连接字符串_致正在备考Access的你,学习重点和题库以及b站优课请查收!...
  2. linux内存管理实验malloc,linux内存管理实验报告.doc
  3. 【spring boot】 禁用/关闭数据源/DataSource
  4. java 接口 this参数_Java BiFunction 接口实例
  5. matplotlib 显示批量图片_chapter4-1 简单数据可视化包Matplotlib整理1
  6. 信息通信建设工程预算定额_通信建设工程概预算
  7. 常见的邮件服务器有哪三种,常见邮件服务器的种类有哪些?分别用什么协议?,常见服务器类型...
  8. 三件套都有什么_床上用品三件套、四件套、21件套都各指什么啊?
  9. 重启服务器之home下文件全没,小白宝典——树莓派实用工具分享(大神绕路)
  10. c语言程序设计章节作业网上,C语言程序设计第17章在线测试