【Quartz】深入Job、JobDetail、JobDataMap、Trigger

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。

Quartz API核心接口有:

  • Scheduler – 与scheduler交互的主要API;
  • Job – 你通过scheduler执行任务,你的任务类需要实现的接口;
  • JobDetail – 定义Job的实例;
  • Trigger – 触发Job的执行;
  • JobBuilder – 定义和创建JobDetail实例的接口;
  • TriggerBuilder – 定义和创建Trigger实例的接口;
  •  

本文工程免费下载

一、Job

 

        在上一节中,Job中定义了实际的业务逻辑,而JobDetail包含Job相关的配置信息。在Quartz中,每次Scheduler执行Job时,在调用其execute()方法之前,它需要先根据JobDetail提供的Job类型创建一个Job class的实例,在任务执行完以后,Job class的实例会被丢弃,Jvm的垃圾回收器会将它们回收。因此编写Job的具体实现时,需要注意:

(1) 它必须具有一个无参数的构造函数;

(2) 它不应该有静态数据类型,因为每次Job执行完以后便被回收,因此在多次执行时静态数据没法被维护。

        在JobDetail中有这么一个成员JobDataMap,JobDataMap是Java Map接口的具体实现,并添加了一些便利的方法用于存储与读取原生类型数据,里面包含了当Job实例运行时,你希望提供给它的所有数据对象。

         可以借助JobDataMap为Job实例提供属性/配置,可以通过它来追踪Job的执行状态等等。对于第一种情况,可以在创建Job时,添加JobDataMap数据,在Job的execute()中获取数据,第二种,则可以在Listener中通过获取JobDataMap中存储的状态数据追踪Job的执行状态。

一个实现了Job接口的Java类就能够被调度器执行。接口如下:

 

 
  1. packageorg.quartz;
  2. publicinterface Job {
  3. public void execute(JobExecutionContext context) throwsJobExecutionException;
  4. }


        很简的,当Job的trigger触发时,Job的execute(..)方法就会被调度器调用。被传递到这个方法里来的JobExecutionContext对象提供了带有job运行时的信息:执行它的调度器句柄、触发它的触发器句柄、job的JobDetail对象和一些其他的项。JobDetail对象是Job在被加到调度器里时所创建的,它包含有很多的Job属性设置,和JobDataMap一样,可以用来存储job实例时的一些状态信息。

 

比如如下任务类

 

 

 

 
[java] view plain copy
  1. <code class="language-java">package com.mucfc;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import org.apache.commons.logging.Log;  
  6. import org.apache.commons.logging.LogFactory;  
  7. import org.quartz.Job;  
  8. import org.quartz.JobDetail;  
  9. import org.quartz.JobExecutionContext;  
  10. import org.quartz.JobExecutionException;  
  11.   
  12. public class NewJob implements Job{  
  13.      static Log logger = LogFactory.getLog(NewJob.class);     
  14.     @Override  
  15.     public void execute(JobExecutionContext context) throws JobExecutionException {  
  16.          System.err.println("Hello!  NewJob is executing."+new Date() );  
  17.     //取得job详情  
  18.          JobDetail jobDetail = context.getJobDetail();     
  19.          // 取得job名称  
  20.          String jobName = jobDetail.getClass().getName();  
  21.          logger.info("Name: " + jobDetail.getClass().getSimpleName());     
  22.          //取得job的类  
  23.          logger.info("Job Class: " + jobDetail.getJobClass());     
  24.          //取得job开始时间  
  25.          logger.info(jobName + " fired at " + context.getFireTime());     
  26.         logger.info("Next fire time " + context.getNextFireTime());   
  27.     }  
  28.   
  29. }  
  30. </code>  

 


        当 Scheduler 调用一个 Job,一个 JobexecutionContext 传递给 execute() 方法。JobExecutionContext 对象让 Job 能访问 Quartz 运行时候环境和 Job 本身的明细数据。这就类似于在 Java Web 应用中的 servlet 访问 ServletContext 那样。通过 JobExecutionContext,Job 可访问到所处环境的所有信息,包括注册到 Scheduler 上与该 Job 相关联的 JobDetail 和 Triiger。

 

 

 

 

二、JobDetail 

 

JobDetail实例是通过JobBuilder类创建的

可以通过导入该类下的所有静态方法

       import static org.quartz.JobBuilder.*;

然后是创建:

 
  1. 创建一个JobDetail实例
  2. JobDetail jobDetail = newJob(NewJob.class).withIdentity("job1_1", "jGroup1").build();

如果不导入静态包:

那么就要用:

 
  1. 创建一个JobDetail实例
  2. obDetail jobDetail = JobBuilder.newJob(NewJob.class).withIdentity("job1_1", "jGroup1").build();

 

对于部署在 Scheduler 上的每一个 Job 只创建了一个 JobDetail 实例。JobDetail 是作为 Job 实例进行定义的。注意到在代码 中不是把 Job 对象注册到 Scheduler;实际注册的是一个 JobDetail 实例。

 

 
  1. public void startSchedule() {
  2. try {
  3. // 1、创建一个JobDetail实例,指定Quartz
  4. JobDetail jobDetail = JobBuilder.newJob(NewJob.class) // 任务执行类
  5. .withIdentity("job1_1", "jGroup1")// 任务名,任务组
  6. .build();
  7. //2、创建Trigger
  8. SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
  9. .withIntervalInSeconds(5) //设置间隔执行时间
  10. .repeatSecondlyForTotalCount(5);//设置执行次数
  11. Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
  12. "trigger1_1","tGroup1").startNow().withSchedule(builder).build();
  13. //3、创建Scheduler
  14. Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
  15. //4、调度执行
  16. scheduler.scheduleJob(jobDetail, trigger);
  17. scheduler.start();
  18. } catch (SchedulerException e) {
  19. e.printStackTrace();
  20. }
  21. }

结果:

 

从上面的代码中可以看JobDetail 被加到 Scheduler 中了,而不是 job。Job 类是作为 JobDetail 的一部份,但是它直到 Scheduler 准备要执行它的时候才会被实例化的。

 

直到执行时才会创建 Job 实例 

Job 的实例要到该执行它们的时候才会实例化出来。每次 Job 被执行,一个新的 Job 实例会被创建。其中暗含的意思就是你的 Job 不必担心线程安全性,因为同一时刻仅有一个线程去执行给定 Job 类的实例,甚至是并发执行同一 Job 也是如此。

 

 

 

       可以看到,我们传给scheduler一个JobDetail实例,因为我们在创建JobDetail时,将要执行的job的类名传给了JobDetail,所以scheduler就知道了要执行何种类型的job;每次当scheduler执行job时,在调用其execute(…)方法之前会创建该类的一个新的实例;执行完毕,对该实例的引用就被丢弃了,实例会被垃圾回收;这种执行策略带来的一个后果是,job必须有一个无参的构造函数(当使用默认的JobFactory时);另一个后果是,在job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留。

        那么如何给job实例增加属性或配置呢?如何在job的多次执行中,跟踪job的状态呢?答案就是:JobDataMap,JobDetail对象的一部分。

 

三、JobDataMap

         JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。

将job加入到scheduler之前,在构建JobDetail时,可以将数据放入JobDataMap,如下示例:

 

 

 
  1. package com.mucfc;
  2. import org.quartz.Job;
  3. import org.quartz.JobDataMap;
  4. import org.quartz.JobExecutionContext;
  5. import org.quartz.JobExecutionException;
  6. import org.quartz.JobKey;
  7. public class NewJob2 implements Job{
  8. @Override
  9. public void execute(JobExecutionContext context) throws JobExecutionException {
  10. JobKey key = context.getJobDetail().getKey();
  11. JobDataMap dataMap = context.getJobDetail().getJobDataMap();
  12. String jobSays = dataMap.getString("jobSays");
  13. float myFloatValue = dataMap.getFloat("myFloatValue");
  14. System.out.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
  15. }
  16. }

 

在job的执行过程中,可以从JobDataMap中取出数据,如下示例:

 

 
  1. package com.mucfc;
  2. import org.quartz.JobBuilder;
  3. import org.quartz.JobDetail;
  4. import org.quartz.Scheduler;
  5. import org.quartz.SchedulerException;
  6. import org.quartz.SimpleScheduleBuilder;
  7. import org.quartz.Trigger;
  8. import org.quartz.TriggerBuilder;
  9. import org.quartz.impl.StdSchedulerFactory;
  10. public class Test {
  11. public void startSchedule() {
  12. try {
  13. // 1、创建一个JobDetail实例,指定Quartz
  14. JobDetail jobDetail = JobBuilder.newJob(NewJob.class) // 任务执行类
  15. .withIdentity("job1_1", "jGroup1")// 任务名,任务组
  16. .build();
  17. JobDetail jobDetail2 = JobBuilder.newJob(NewJob2.class)
  18. .withIdentity("job1_2", "jGroup1")
  19. .usingJobData("jobSays", "Hello World!")
  20. .usingJobData("myFloatValue", 3.141f)
  21. .build();
  22. //2、创建Trigger
  23. SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
  24. .withIntervalInSeconds(5) //设置间隔执行时间
  25. .repeatSecondlyForTotalCount(5);//设置执行次数
  26. Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
  27. "trigger1_1","tGroup1").startNow().withSchedule(builder).build();
  28. //3、创建Scheduler
  29. Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
  30. //4、调度执行
  31. scheduler.scheduleJob(jobDetail2, trigger);
  32. scheduler.start();
  33. } catch (SchedulerException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. public static void main(String[] args) {
  38. Test test=new Test();
  39. test.startSchedule();
  40. }
  41. }


结果:

 

 

四、 Trigger

        Trigger对象是用来触发执行Job的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。触发器也有一个和它相关的JobDataMap,它是用来给被触发器触发的job传参数的。Quartz有一些不同的触发器类型,不过,用得最多的是SimpleTrigger和CronTrigger。

        如果我们需要在给定时刻执行一次job或者在给定时刻触发job随后间断一定时间不停的执行的话,SimpleTrigger是个简单的解决办法;如果我们想基于类似日历调度的触发job的话,比如说,在每个星期五的中午或者在每个月第10天的10:15触发job时,CronTrigger是很有用的。

         为什么用jobs和triggers呢?很多任务调度器并没有任务和触发器的概念,一些任务调度器简单定义一个“job”为在一个执行时间伴随一些小任务标示,其他的更像Quartz里job和trigger对象的联合体。在开发Quartz时,开发者们决定,在调度时间表和在这上面运行的工作应该分开。这是很有用的。

        例如,job能够独立于触发器被创建和储存在任务调度器里,并且,很多的触发器能够与同一个job关联起来。这个松耦合的另一个好处就是在与jobs关联的触发器终止后,我们能够再次配置保留在调度器里的jobs,这样的话,我们能够再次调度这些jobs而不需要重新定义他们。我们也可以在不重新定义一个关联到job的触发器的情况下,修改或替代它。

         当Jobs和triggers被注册到Quartz的调度器里时,他们就有了唯一标示符。他们也可以被放到“groups”里,Groups是用来组织分类jobs和triggers的,以便今后的维护。在一个组里的job和trigger的名字必须是唯一的,换句话说,一个job和trigger的全名为他们的名字加上组名。如果把组名置为”null”,系统会自动给它置为Scheduler.DEFAULT_GROUP

 

Scheduler在使用之前需要实例化。一般通过SchedulerFactory来创建一个实例。有些用户将factory的实例保存在JNDI中,但直接初始化,然后使用该实例也许更简单(见下面的示例)。

scheduler实例化后,可以启动(start)、暂停(stand-by)、停止(shutdown)。注意:scheduler被停止后,除非重新实例化,否则不能重新启动;只有当scheduler启动后,即使处于暂停状态也不行,trigger才会被触发(job才会被执行)。

 

五、SimpleTrigger的介绍

正如其名所示,SimpleTrigger对于设置和使用是最为简单的一种 QuartzTrigger。它是为那种需要在特定的日期/时间启动,且以一个可能的间隔时间重复执行 n 次的 Job 所设计的。
我们前面已经在一个简单的Quartz的例子里使用过了SimpleTrigger,我们通过

 
  1. SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
  2. //设置间隔执行时间
  3. .withIntervalInSeconds(5)
  4. //设置执行次数
  5. .withRepeatCount(4);
 
  1. Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
  2. "trigger1_1","tGroup1").startNow().withSchedule(builder).build();


或者无限执行

 

 

 
  1. SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
  2. //设置间隔执行时间
  3. .withIntervalInSeconds(5)
  4. //设置执行次数
  5. .repeatForever();
  6. Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
  7. "trigger1_1","tGroup1").startNow().withSchedule(builder).build();


对于Quartz而言,它还不能满足我们的触发情况,所以它仅仅是用于一些简单的触发情况;

 

 

 

六、CronTrigger

        CronTrigger 允许设定非常复杂的触发时间表。然而有时也许不得不使用两个或多个 SimpleTrigger来满足你的触发需求,这时候,你仅仅需要一个 CronTrigger 实例就够了。顾名思义,CronTrigger 是基于 Unix类似于 cron 的表达式。例如,你也许有一个 Job,要它在星期一和星期五的上午 8:00-9:00间每五分钟执行一次。假如你试图用 SimpleTrigger 来实现,你或许要为这个 Job 配置多个Trigger。然而,你可以使用如下的表达式来产生一个遵照这个时间表触发的 Trigger;
比如:

 

 

 
  1. // 创建Trigger
  2. CronScheduleBuilder builder2 = CronScheduleBuilder.cronSchedule("0 0/5 8 * * *");//8:00-8:55,每隔5分钟执行
  3. /**
  4. builder2 = CronScheduleBuilder.dailyAtHourAndMinute(12, 30);
  5. **/
  6. Trigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger1_1","tGroup1").startNow().withSchedule(builder2).build();

 

 

        因为 CronTrigger内建的如此强的灵活性,也与生俱来可用于创建几乎无所限制的表达式,且因为支持unix的cron表达式,则做为企业应用,我们的操作系统一般也都以unxi操作系统为主,所以掌握CronTrigger的使用费用有必要,我们将在后面对CronTrigger 进行详细的介绍。cron 表达式的格式见下一节。

七、Job与Trigger的关系

        大家都知道,一个作业,比较重要的三个要素就是Schduler,jobDetail,Trigger;而Trigger对于job而言就好比一个驱动器;没有触发器来定时驱动作业,作业就无法运行;对于Job而言,一个job可以对应多个Trigger,但对于Trigger而言,一个Trigger只能对应一个job;所以一个Trigger 只能被指派给一个 Job;如果你需要一个更复杂的触发计划,你可以创建多个 Trigger 并指派它们给同一个 Job。Scheduler 是基于配置在 Job上的 Trigger 来决定正确的执行计划的,下面就是为同一个 JobDetail 使用多个Trigger;

 

转自:http://blog.csdn.net/evankaka

本文工程免费下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图形界面上机作业

1、 制作一个如图所示的界面&#xff08;使用FlowLayout布局&#xff09;&#xff0c;不要求实现功能。 2、设计一个用标签、文本行与按钮来登录的界面&#xff08;用GridLayout布局方式&#xff09;。如图所示。 转载于:https://www.cnblogs.com/quan-2723365710/p/10881691.h…

【Quartz】Spring3.2.9 + Quqrtz2.2.1 实现定时实例

一、工程创建 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、新建一个工程&#xff0c;导入相应的包Spring3.2.9Quqrtz2.2.1commons-logging 集成起来比较简单,对线程无需任何理解&a…

第十二周作业

这个作业属于那个课程c语言这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/computer-scienceclass4-2018/homework/3236我在这个课程的目标是学习掌握单向链表&#xff0c;掌握二级指针的概念&#xff0c;以及指针数组这个作业在哪个具体方面帮助我实现目标前面3道题…

【Quartz】插件的使用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Quartz 框架提供了几种用于扩展平台能力的方式。通过使用各种 "钩子" (通常指的就是扩展点)&#xff0c;Quartz 变得很容易被扩…

自动化运维平台(前端vue)

前端的大体流程&#xff1a;首先是Login登录组件&#xff0c;当输入用户名和密码之后&#xff0c;发送post请求到后端&#xff0c;然后根据返回的数据的是否正常&#xff0c;如果正常&#xff0c;将返回的token以及用户名保存到sessionStorage中&#xff0c;并使用导航守卫进行…

Quartz 之入门示例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 环境:XPMyeclipse6.5JDK1.6 quartz官网:http://www.quartz-scheduler.org/ 参考资料 1 Quartz任务调度快速入门 http://www.blogjava…

CSS3最颠覆性的动画效果,基本属性[3D]

和2D一样也是transform 即变形 1)rotateX rotateY rotateZ&#xff08;也可以用transform-origin来设置旋转中心点&#xff09; 2)透视(perspective) 给父亲加透视&#xff0c;透视就是模拟眼睛到物体的距离&#xff0c;近大远小&#xff0c;即数值越小&#xff0c;3D越明显 理…

解决报错 :A component required a bean of type ‘gentle.test.Show‘ that could not be found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 启动工程失败&#xff0c;报错如题&#xff1a; A component required a bean of type gentle.test.Show that could not be found.…

解决.quartz.ObjectAlreadyExistsException: Unable to store Job : ‘jyGroup.jyJob‘, because one already

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 报错如题&#xff1a; 定时任务出现异常 &#xff1a; org.quartz.ObjectAlreadyExistsException: Unable to store Job : jyGroup.…

WeMos-D1R2的使用

2019独角兽企业重金招聘Python工程师标准>>> WeMos介绍 WeMos-D1R2一个基于ESP8266-12 Wifi模块的Arduino-UNO开发板。也就是说&#xff0c;WeMos-D1R2是一个具有wifi功能的Arduino开发板&#xff0c;但WeMos-D1R2与Arduino-UNO的引脚不是一一对应的&#xff0c;其对…

RabbitMQ MQTT协议和AMQP协议

RabbitMQ MQTT协议和AMQP协议 1 序言... 1 1.1 RabbitMq结构... 1 1.2 RabbitMq消息接收... 4 1.3 Exchange种类和消息发送模式... 4 1.4 RabbitMq的协议... 6 1.4.1 AMQP协议... 6 1.4.2 MQTT协议... 8 2 RabbitMq服务器安装和使用…

Quartz 定时任务(Scheduler)的 3 种实现方式

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 PS&#xff1a;第 3 种最简单。 一、引入 jar 。 <!-- quartz 定时任务调度 --><dependency><groupId>org.springfr…

加速财务自由的7种理财方法

有人说财务自由是个遥不可及的路&#xff0c;有人却觉得想要在财务上成功很简单&#xff0c;到底财务自由有没有一个正确的方法或是被证明的技巧可以被实现&#xff1f;如果你现在还没达成或是正在达成&#xff0c;底下这7种简单有效的行动与方法可以加速你建构财务自由之路。 …

Git 安装及 idea 配置 Git

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.git官网下载地址&#xff1a;点此跳转git官网 git具体安装不做详细叙述。 2.打开idea 点击Configure -> Settings 3.选择Git 找到…

第六章学习小结

本章学习了图的结构及应用&#xff0c; 首先是图的分类&#xff0c;图分为无向图、有向图、完全图、连通图、强连通图、带权图、稀疏图、稠密图等等。 图的存储方式有两大类&#xff0c;以边集合方式的表示法和以链接方式的表示法。其中&#xff0c;以边集合方式表示的为邻接矩…

idea 玩转 码云 -- idea安装码云插件

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 在git盛行的今天&#xff0c;码云成为中国程序员的第二github&#xff0c;而且还可以免费使用私人空间。下面就开始码云之旅吧。 0.创建…

阿里云的物联网之路

阿里云的物联网之路 作者 | 刘洪峰 责编 | 唐小引 本文首发于 CSDN 微信&#xff08;ID&#xff1a;CSDNnews&#xff09; 原文链接 未来十到二十年&#xff0c;大家基本已经形成了一个共识&#xff0c;那便是新格局的奠定将由 AI 和物联网技术来支撑。放眼国内&#xff0c;在…

面向对象-多态,反射

抽象父类 # 抽象父类&#xff1a;拥有抽象方法(子类共有的方法&#xff0c;但是父类不能有具体的实现体)的父类 # 抽象方法&#xff1a;方法名是具体的&#xff0c;但是实现体是抽象的(在子类中重写来具象化) ​ # 注意点&#xff1a;有抽象方法的父类不能被实例化&#…

CVPR2014: DeepID解读

上周五就要发的&#xff0c;拖........拖.......拖到现在&#xff0c;文中有不准确的地方&#xff0c;欢迎批评指正。DeepID是一种特征提取的算法&#xff0c;由港中文汤晓鸥团队于2014年提出&#xff0c;发表于CVPR2014。其应用领域是人脸识别的子领域——人脸验证&#xff0c…

成大事必备9种能力 9种手段 9种心态(图)

成大事必备9种能力 1、摆正心态&#xff0c;敢于面对现实 对于那些不停地抱怨现实恶劣的人来说&#xff0c;不能称心如意的现实&#xff0c;就如同生活的牢笼&#xff0c;既束缚手脚&#xff0c;又束缚身心&#xff0c;因此常屈从于现实的压力&#xff0c;成为懦弱者;而那些…