Quartz快速入门指南-W3c

一、什么是Quartz

车票购票,当你下单后,后台就会插入一条待支付的task(job),一般是30分钟,超过30min后就会执行这个job,去判断你是否支付,未支付就会取消此次订单;当你支付完成之后,后台拿到支付回调后就会再插入一条待消费的task(job),Job触发日期为火车票上的出发日期,超过这个时间就会执行这个job,判断是否使用等。

(1)首先我们需要定义实现一个定时功能的接口,我们可以称之为Task(或Job),如定时发送邮件的task(Job),重启机器的task(Job),优惠券到期发送短信提醒的task(Job),实现接口如下:


(2)有了任务之后,还需要一个能够实现触发任务去执行的触发器,触发器Trigger最基本的功能是指定Job的执行时间,执行间隔,运行次数等。


(3)有了Job和Trigger后,怎么样将两者结合起来呢?即怎样指定Trigger去执行指定的Job呢?这时需要一个Schedule,来负责这个功能的实现。


上面三个部分就是Quartz的基本组成部分:

调度器:Scheduler
任务:JobDetail
触发器:Trigger,包括SimpleTrigger和CronTrigger

二、Quartz Demo搭建

下面来利用Quartz搭建一个最基本的Demo。

1、导入依赖的jar包:

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

2、新建一个能够打印任意内容的Job:

/*** Created by wanggenshen* Date: on 2018/7/7 16:28.* Description: 打印任意内容*/
public class PrintWordsJob implements Job{@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));}
}

3、创建Schedule,执行任务:

/*** Created by wanggenshen* Date: on 2018/7/7 16:31.* Description: XXX*/
public class MyScheduler {public static void main(String[] args) throws SchedulerException, InterruptedException {// 1、创建调度器SchedulerSchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();// 2、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class).withIdentity("job1", "group1").build();// 3、构建Trigger实例,每隔1s执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").startNow()//立即生效.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)//每隔1s执行一次.repeatForever()).build();//一直执行//4、执行scheduler.scheduleJob(jobDetail, trigger);System.out.println("--------scheduler start ! ------------");scheduler.start();//睡眠TimeUnit.MINUTES.sleep(1);scheduler.shutdown();System.out.println("--------scheduler shutdown ! ------------");}
}

运行程序,可以看到程序每隔1s会打印出内容,且在一分钟后结束:

三、Quartz核心详解

下面就程序中出现的几个参数,看一下Quartz框架中的几个重要参数:

Job和JobDetail
JobExecutionContext
JobDataMap
Trigger、SimpleTrigger、CronTrigger

(1)Job和JobDetail

Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。

JobDetail用来绑定Job,为Job实例提供许多属性:

  • name
  • group
  • jobClass
  • jobDataMap

JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

为什么设计成JobDetail + Job,不直接使用Job

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。
这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

(2)JobExecutionContext

JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息。
当Schedule调度执行一个Job的时候,就会将JobExecutionContext传递给该Job的execute()中,Job就可以通过JobExecutionContext对象获取信息。

JobDataMap实现了JDK的Map接口,可以以Key-Value的形式存储数据。
JobDetail、Trigger都可以使用JobDataMap来设置一些参数或信息,
Job执行execute()方法的时候,JobExecutionContext可以获取到JobDataMap中的信息:

JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class)                        .usingJobData("jobDetail1", "这个Job用来测试的")                 .withIdentity("job1", "group1").build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").usingJobData("trigger1", "这是jobDetail1的trigger").startNow()//立即生效.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)//每隔1s执行一次.repeatForever()).build();//一直执行

Job执行的时候,可以获取到这些参数信息:

    @Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println(jobExecutionContext.getJobDetail().getJobDataMap().get("jobDetail1"));System.out.println(jobExecutionContext.getTrigger().getJobDataMap().get("trigger1"));String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));}

(4)Trigger、SimpleTrigger、CronTrigger

Trigger

Trigger是Quartz的触发器,会去通知Scheduler何时去执行对应Job。

new Trigger().startAt():表示触发器首次被触发的时间;
new Trigger().endAt():表示触发器结束触发的时间;

SimpleTrigger

SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。
下面的程序就实现了程序运行5s后开始执行Job,执行Job 5s后结束执行:

Date startDate = new Date();
startDate.setTime(startDate.getTime() + 5000);Date endDate = new Date();endDate.setTime(startDate.getTime() + 5000);Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").usingJobData("trigger1", "这是jobDetail1的trigger").startNow()//立即生效.startAt(startDate).endAt(endDate).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)//每隔1s执行一次.repeatForever()).build();//一直执行

SimpleTrigger的属性包括:开始时间、结束时间、重复次数以及重复的间隔

重复次数,可以是0、正整数,以及常量SimpleTrigger.REPEAT_INDEFINITELY。

重复的间隔,必须是0,或者long型的正数,表示毫秒。注意,如果重复间隔为0,trigger将会以重复次数并发执行(或者以scheduler可以处理的近似并发数)。

endTime属性的值会覆盖设置重复次数的属性值;比如,你可以创建一个trigger,在终止时间之前每隔10秒执行一次,你不需要去计算在开始时间和终止时间之间的重复次数,只需要设置终止时间并将重复次数设置为REPEAT_INDEFINITELY(当然,你也可以将重复次数设置为一个很大的值,并保证该值比trigger在终止时间之前实际触发的次数要大即可)。

例1、指定时间开始触发,不重复:

    SimpleTrigger trigger = (SimpleTrigger) newTrigger() .withIdentity("trigger1", "group1").startAt(myStartTime)                     // some Date .forJob("job1", "group1")                 // identify job with name, group strings.build();

例2、指定时间触发,每隔10秒执行一次,重复10次:

    trigger = newTrigger().withIdentity("trigger3", "group1").startAt(myTimeToStartFiring)  // if a start time is not given (if this line were omitted), "now" is implied.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings.forJob(myJob) // identify job with handle to its JobDetail itself                   .build();

例3、5分钟以后开始触发,仅执行一次:

    trigger = (SimpleTrigger) newTrigger() .withIdentity("trigger5", "group1").startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future.forJob(myJobKey) // identify job with its JobKey.build();

例4、立即触发,每个5分钟执行一次,直到22:00:

    trigger = newTrigger().withIdentity("trigger7", "group1").withSchedule(simpleSchedule().withIntervalInMinutes(5).repeatForever()).endAt(dateOf(22, 0, 0)).build();

例5、建立一个触发器,将在下一个小时的整点触发,然后每2小时重复一次:

    trigger = newTrigger().withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group.startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00")).withSchedule(simpleSchedule().withIntervalInHours(2).repeatForever())// note that in this example, 'forJob(..)' is not called which is valid // if the trigger is passed to the scheduler along with the job  .build();scheduler.scheduleJob(trigger, job);

TriggerBuilder(以及Quartz的其它builder)会为那些没有被显式设置的属性选择合理的默认值。

比如:如果你没有调用withIdentity(..)方法,TriggerBuilder会为trigger生成一个随机的名称;

如果没有调用startAt(..)方法,则默认使用当前时间,即trigger立即生效。

CronTrigger

CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的,先了解下Cron表达式:
由7个子表达式组成字符串的,格式如下:

[秒] [分] [小时] [日] [月] [周] [年]

Cron表达式的语法比较复杂,
如:* 30 10 ? * 2-6 *
表示(从后往前看)
[指定年份] 的[ 周一到周五][指定月][不指定日][上午10时][30分][指定秒]

又如:00 00 00 ? * 10,11,12 1#5 2018
表示2018年10、11、12月的第一周的星期五这一天的0时0分0秒去执行任务。

可通过在线生成Cron表达式的工具:http://cron.qqe2.com/ 来生成自己想要的表达式。

下面的代码就实现了每周一到周五上午10:30执行定时任务

/*** Created by wanggenshen* Date: on 2018/7/7 20:06.* Description: XXX*/
public class MyScheduler2 {public static void main(String[] args) throws SchedulerException, InterruptedException {// 1、创建调度器SchedulerSchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();// 2、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class).usingJobData("jobDetail1", "这个Job用来测试的").withIdentity("job1", "group1").build();// 3、构建Trigger实例,每隔1s执行一次Date startDate = new Date();startDate.setTime(startDate.getTime() + 5000);Date endDate = new Date();endDate.setTime(startDate.getTime() + 5000);CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").usingJobData("trigger1", "这是jobDetail1的trigger").startNow()//立即生效.startAt(startDate).endAt(endDate).withSchedule(CronScheduleBuilder.cronSchedule("* 30 10 ? * 2-6 2018")).build();//4、执行scheduler.scheduleJob(jobDetail, cronTrigger);System.out.println("--------scheduler start ! ------------");scheduler.start();System.out.println("--------scheduler shutdown ! ------------");}
}

Quartz 定时器 定时任务相关推荐

  1. 定时器 java qua_【spring-boot】 springboot整合quartz实现定时任务

    在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的. spring支持多种定时任务的实现.我们来介绍下使用spring的定时器和使用quartz定时器 1.我们使用s ...

  2. Quartz定时器与定时任务知识概括

    Quartz定时器与定时任务知识概括 定时任务调度 其他定时器 Quartz简介 Quartz简单入门 Spring和Quartz集成 SSMM和Quartz集成 Quartz集群 Quartz配置 ...

  3. quartz定时器依赖_JAVA使用quartz添加定时任务,并依赖注入对象操作

    最近在写定时任务,以前没接触过.查了些相关资料说使用quartz定时框架. 需要配置文件:config-quartz.xml 相关配置如下(红色部分是之后添加的,在后面步骤会说明): xsi:sche ...

  4. spring框架使用Quartz执行定时任务实例详解

    版权声明:本文为博主原创文章,如需转载,请标明出处. https://blog.csdn.net/alan_liuyue/article/details/80382324 Quartz简介 1.Qua ...

  5. 第四十章:基于SpringBoot Quartz完成定时任务分布式多节点负载持久化

    在上一章[第三十九章:基于SpringBoot & Quartz完成定时任务分布式单节点持久化]中我们已经完成了任务的持久化,当我们创建一个任务时任务会被quartz定时任务框架自动持久化到数 ...

  6. spring中配置quartz定时器

    spring中配置quartz定时器 最近项目中用到定时器,项目用的spring所以想在spring中配置一下定时器,看到网上用quartz的比较多,所以就搜了一下.参考:http://blog.cs ...

  7. 第9章 Quartz定时器和发送Email

    开心一笑 [从年初的一无所有,到年终的身无分文,唉,我这不忘初心...] 新书购买 戳图购买 >>> 9.1 使用Quartz定时器 9.1.1 Quartz概述 Quartz是一个 ...

  8. SpringBoot结合Quartz实现定时任务

    <从零打造项目>系列文章 工具 比MyBatis Generator更强大的代码生成器 ORM框架选型 SpringBoot项目基础设施搭建 SpringBoot集成Mybatis项目实操 ...

  9. 个人博客系统开发总结之 quartz定时器

    一个可以自己配置,即配即用的quartz定时器封装. pom.xml配置 <!-- https://mvnrepository.com/artifact/org.quartz-scheduler ...

  10. java定时器、Spring定时器和Quartz定时器

    当前java程序中能够实现定时的主要有三种方式,分别是:java定时器,spring定时器,quartz定时器. 下面依次讲讲他们的应用! java定时器的应用    其实java很早就有解决定时器任 ...

最新文章

  1. 最近最近在微软的Mobile Soft factory
  2. 软件测试用python一般用来做什么-python软件测试
  3. 哎!马上要涉水了,装修的水!
  4. 【python】队列——用链表实现队列操作
  5. linux安全检测及防护,Linux安全检测及防护-单选题.doc
  6. 如何知道osg模型每个节点的名称
  7. 基本类型理解巩固及补码原理总结
  8. qt根据散点图拟合曲线_R可视化 | 散点图系列(1)
  9. POJ 3671 DP or 乱搞
  10. 凸优化第八章几何问题 8.4 极值体积椭圆
  11. Redis设计与实现(导航)
  12. tsmaster中文版(M3U8下载器)
  13. java 设置纸张大小设置_java page如何设置纸张
  14. 问题驱动,提出问题,发现问题,解决问题
  15. 年度全球十大突破性技术公布,TikTok推荐算法等入选
  16. Egret Wing 项目结构
  17. 智能世代的工业/嵌入式网络与I/O桥接芯片解决方案
  18. GUI:简易计算器设计
  19. android慢快门相机,慢快门app-Slow Shutter Cam官网版(附教程)预约 _5577安卓网
  20. Tomb.Finance的每周更新(5.23-5.29)

热门文章

  1. el-select 下拉框样式修改
  2. coap python_一步步搭建物联网系统——RESTful的CoAP协议
  3. 谷歌添加vue开发工具插件
  4. 自顶向下语法分析的作业
  5. 如何计算虚拟化vcpu_【虚拟化实战】VM设计之一vCPU
  6. linux虚拟化cpu的绑定,为虚拟机vCPU绑定物理CPU
  7. python实现图片转字符画
  8. 改变世界的程序员—Jack Dorsey
  9. 串口通讯---实现 PC 端之间串口连接传输文件
  10. 如何对计算机进行硬盘的分区,使用分区助手如何对磁盘进行快速分区?