注:本文来源于:是Guava不是瓜娃  《定时任务框架Quartz-(一)Quartz入门与Demo搭建》

一、什么是Quartz

什么是Quartz?

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:

持久性作业 - 就是保持调度定时的状态;
作业管理 - 对调度作业进行有效的管理;

大部分公司都会用到定时任务这个功能。

拿火车票购票来说,当你下单后,后台就会插入一条待支付的task(job),一般是30分钟,超过30min后就会执行这个job,去判断你是否支付,未支付就会取消此次订单;当你支付完成之后,后台拿到支付回调后就会再插入一条待消费的task(job),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:

 package com.todaytech.GdsdFs.QuartzDemo.Demo2;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random; import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 新建一个能够打印任意内容的Job:
* @author admin
*
*/
public class PrintWordsJob implements Job{ @Override
public 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,执行任务:

 package com.todaytech.GdsdFs.QuartzDemo.Demo2;

import java.util.concurrent.TimeUnit;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory; /**
* 创建Schedule,执行任务:
* @author admin
*
*/
public class MyScheduler {
public static void main(String[] args) throws SchedulerException, InterruptedException {
// 1、创建调度器Scheduler
SchedulerFactory 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对象获取信息。

主要信息有:

(3)JobExecutionContext

JobDataMap实现了JDK的Map接口,可以以Key-Value的形式存储数据。

JobDetail、Trigger都可以使用JobDataMap来设置一些参数或信息,

Job执行execute()方法的时候,JobExecutionContext可以获取到JobExecutionContext中的信息:

如:

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执行的时候,可以获取到这些参数信息:

@Override
public 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();//一直执行

CronTrigger

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

由7个子表达式组成字符串的,格式如下:

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

Cron表达式的语法比较复杂,

如:* 30 10 ? * 1/5 *

表示(从后往前看)

[指定年份] 的[ 周一到周五][指定月][不指定日][上午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执行定时任务

 package com.todaytech.GdsdFs.QuartzDemo.Demo2;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 下面的代码就实现了每周一到周五上午10:30执行定时任务
* @author admin
*
*/
public class MyScheduler2 {
public static void main(String[] args) throws SchedulerException, InterruptedException {
// 1、创建调度器Scheduler
SchedulerFactory 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 ? * 1/5 2018"))
.build(); //4、执行
scheduler.scheduleJob(jobDetail, cronTrigger);
System.out.println("--------scheduler start ! ------------");
scheduler.start();
System.out.println("--------scheduler shutdown ! ------------"); }
}

定时任务框架Quartz-(一)Quartz入门与Demo搭建的更多相关文章

  1. atititt.java定时任务框架选型Spring Quartz 注解总结

    atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz  (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...

  2. Python中定时任务框架APScheduler的快速入门指南

    前言 大家应该都知道在编程语言中,定时任务是常用的一种调度形式,在Python中也涌现了非常多的调度模块,本文将简要介绍APScheduler的基本使用方法. 一.APScheduler介绍 APSc ...

  3. java定时任务框架Quartz入门与Demo搭建

  4. 【Quartz】Quartz的搭建、应用(单独使用Quartz)

    Quartz在Java构建的系统中,是十分常用的定时任务框架. 本文,记录.介绍Quartz的简单入门的单独搭建(此文入门学习Quartz为主,并非基于Spring托管形式). > 参考的优秀资 ...

  5. 第一节: Timer的定时任务的复习、Quartz.Net的入门使用、Aop思想的体现

    一. 前奏-Timer类实现定时任务 在没有引入第三方开源的定时调度框架之前,我们处理一些简单的定时任务同时都是使用Timer类, DotNet中的Timer类有三个,分别位于不同的命名空间下,分别是 ...

  6. 集群式Quartz定时任务框架实践

    在日常开发汇总,经常会遇到需要定时任务的场景,简单的,可以使用Spring的定时任务调度框架,也可以使用Quartz.无论使用哪种,都需要解决一个问题,那就是集群问题.一般情况下,定时任务能且仅能运行 ...

  7. Quartz -----定时任务框架

    一.什么是Quartz     由java开发用来执行定时任务,类似于java.util.Timer.   但是相较于Timer,quartz增加了很多功能:                  持久性 ...

  8. Quartz.Net的使用(简单配置方法)定时任务框架

    Quartz.dll 安装nuget在线获取dll包管理器,从中获取最新版 Quartz.Net是一个定时任务框架,可以实现异常灵活的定时任务,开发人员只要编写少量的代码就可以实现“每隔1小时执行”. ...

  9. quartz.net定时任务框架详解

    C#做定时任务:一是Timer:而是Quartz.net:本文就学习一下Quartz.net框架 Quartz.net非常的灵活,开发人员能用很少的代码就能完成“每隔一小时执行”.“每天2点执行”.“ ...

随机推荐

  1. [2019.03.21]LF, CR, CRLF and LFCR(?)

    开玩笑的啦,没有LFCR这种沙雕东西 为什么突然想起来写这个呢,是因为先前照着shell画llehs的时候,总报错,改正了以后又因为看不见而在上一篇博客上没有写明,所以过来好好写一写咯. 可以看出报错 ...

  2. 洛谷 P5110 块速递推

    题目大意: 给定一个数列a满足递推式 \(An=233*an-1+666*an-2,a0=0,a1=1\) 求这个数列第n项模\(10^9+7\)的值,一共有T组询问 \(T<=10^7\) \ ...

  3. Django 中使用ImgFiled 和FileFiled

    1.使用ImgFiled class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, * ...

  4. 第一周java学习总结

    学号 20175206 <Java程序设计>第一周学习总结 教材学习内容总结 第一章是关于JAVA入门的注意事项: 第一章主要按照顺序讲了JAVA的地位,诞生,特点,JDK的安装,一些ja ...

  5. 使用vcastr22.swf做flash版网页视频播放器

    flash的安装设置参考  Flash设置(各种版本浏览器包括低版本IE) 百度搜索下载vcastr22.swf文件 然后使用方式很简单,浏览器安装flash相关插件就能看了 视频路径主要在这里,视频 ...

  6. 【优秀的图片后期编辑工具】Luminar 3.1 for Mac

     [简介] 今天和大家分享最新的 Luminar for Mac 3.1 版本,支持中文界面,Luminar是一款Mac上优秀的图片后期处理工具,功能类似 Photoshop Lightroom 等软 ...

  7. prometheus 集群

    思路一 统一区域的监控目标,prometheus server两台监控相同的目标群体. 改变后 上面这个变化对于监控目标端,会多出一倍的查询请求,但在一台prometheus server宕机的情况下 ...

  8. Python解析xml文档实战案例

    xml文档 <?xml version="1.0" ?> <!DOCTYPE PubmedArticleSet PUBLIC "-//NLM//DTD ...

  9. DirectX11 With Windows SDK--23 立方体映射:动态天空盒的实现

    前言 上一章的静态天空盒已经可以满足绝大部分日常使用了.但对于自带反射/折射属性的物体来说,它需要依赖天空盒进行绘制,但静态天空盒并不会记录周边的物体,更不用说正在其周围运动的物体了.因此我们需要在运 ...

  10. JS代码风格自动规整工具Prettier

    问题背景 通常使用 ESLint做代码风格检查检查, 和部分代码质量检查. 但是使用ESLint在入库时候, 会产生很多的代码修正工作, 需要开发者一个一个的修改. 如果很多,并且时间紧迫,甚是尴尬. ...