注:本文来源于:是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. C#中字符串转日期类型

    1,yyyyMMdd DateTime date = DateTime.ParseExact(", "yyyyMMdd", System.Globalization.Cu ...

  2. Python3.7源码在windows(VS2015)下的编译和安装

    Python3.7源码在windows(VS2015)下的编译和安装 下载官方源码,使用vs2015(WIN10SDK),最python3.7.0的源码进行编译,编译出不同的版本(release,de ...

  3. [模板] tarjan/联通分量/dfs树

    //to update 边的分类 有向图边分为四类: 树边, 前向边, 返祖边(后向边), 横叉边. 上图: 判定 有向图 对图进行dfs, 不考虑已经遍历过的点, 得到dfs序 \(dfn_i\). ...

  4. 用ES6创建一个简单工厂模式

    1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式.我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂.工厂模式根据抽象程度的不同可以分为:简 ...

  5. global与nonlocal关键字

    在Python中,当引用一个变量的时候,对这个变量的搜索是按找本地作用域(Local).嵌套作用域(Enclosing function locals).全局作用域(Global).内置作用域(bui ...

  6. logstash的output配置中指定elasticsearch的template

    转自:https://blog.csdn.net/felix_yujing/article/details/78930389 之前采用的是通过filebeat收集nginx的日志,直接到elastic ...

  7. pandas的读写

    import as pd import numpy as np import matplotlib.pyplot as plt #df.to_excel('C:Users/history/Deskto ...

  8. 洛伦兹曲线(Lorenz curve)提升指数、提升表和提升图

    sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campai ...

  9. GCC 警告

    -w -W禁止/开启 编译警告的打印.这个警告不建议使用.大约2012年底,公司代码进行一次大重构,另外从Codeblock集成开发环境转向Makefile管理,Makefile里面默认使用了-w,因 ...

  10. MySQL启动出现The server quit without updating PID file错误解决办法

    启动mysql服务的时候报下面这个错: 之间网上搜了各种办法,有重新初始化的(这怎么可能,里面还有数据...),有修改启动脚本的等等,但是都没用. 其实解决办法非常简单粗暴,那就是把/etc/my.c ...