前言

项目中遇到一个,需要 客户自定任务启动时间 的需求。原来一直都是在项目里硬编码一些定时器,所以没有学习过。

很多开源的项目管理框架都已经做了 Quartz 的集成。我们居然连这么常用得东西居然没有做成模块化,实在是不应该。


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

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

官方文档:Documentation (quartz-scheduler.org)、Quartz Enterprise Job Scheduler 2.3.0 API

这一篇先记一下基础使用、springboot 内的使用,以及灵活配置方式。

基础使用

Quartz 的核心类有以下三部分:

  • 任务 Job :需要实现的任务类,实现 execute() 方法,执行后完成任务。
  • 触发器 Trigger :包括 SimpleTrigger 和 CronTrigger。
  • 调度器 Scheduler :任务调度器,负责基于 Trigger触发器,来执行 Job任务。

主要关系如下:

Demo

按照官网的 Demo,搭建一个纯 maven 项目,添加依赖:

<!-- 核心包 -->
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version>
</dependency>
<!-- 工具包 -->
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.3.0</version>
</dependency>

新建一个任务,实现了 org.quartz.Job 接口:

public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务被执行了。。。");}
}

main 方法,创建调度器、jobDetail 实例、trigger 实例、执行:

public static void main(String[] args) throws Exception {// 1.创建调度器 SchedulerSchedulerFactory factory = new StdSchedulerFactory();Scheduler scheduler = factory.getScheduler();// 2.创建JobDetail实例,并与MyJob类绑定(Job执行内容)JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();// 3.构建Trigger实例,每隔30s执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(30).repeatForever()).build();// 4.执行,开启调度器scheduler.scheduleJob(job, trigger);System.out.println(System.currentTimeMillis());scheduler.start();//主线程睡眠1分钟,然后关闭调度器TimeUnit.MINUTES.sleep(1);scheduler.shutdown();System.out.println(System.currentTimeMillis());
}

日志打印情况:

JobDetail

JobDetail 的作用是绑定 Job,是一个任务实例,它为 Job 添加了许多扩展参数。

主要字段 涵义、作用
name 任务名称
group 任务分组,默认分组 DEFAULT
jobClass 任务类,就是上面 Demo 中的 MyJob 的路径
jobDataMap 任务参数信息。JobDetail、Trigger 都可以使用 JobDataMap 来设置一些参数或信息。

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

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

JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中。

这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。

而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以 规避并发访问 的问题。

JobExecutionContext

  • 当 Scheduler 调用一个 job,就会将 JobExecutionContext 传递给 Job 的 execute() 方法;
  • Job 能通过 JobExecutionContext 对象访问到 Quartz 运行时候的环境以及 Job 本身的明细数据。

任务实现的 execute() 方法,可以通过 context 参数获取。

public interface Job {void execute(JobExecutionContext context)throws JobExecutionException;
}

在 Builder 建造过程中,可以使用如下方法:

usingJobData("tiggerDataMap", "测试传参")

在 execute 方法中获取:

context.getTrigger().getJobDataMap().get("tiggerDataMap");
context.getJobDetail().getJobDataMap().get("tiggerDataMap");

Job 状态参数

有状态的 job 可以理解为多次 job调用期间可以持有一些状态信息,这些状态信息存储在 JobDataMap 中。

而默认的无状态 job,每次调用时都会创建一个新的 JobDataMap。

示例如下:

//多次调用 Job 的时候,将参数保留在 JobDataMap
@PersistJobDataAfterExecution
public class JobStatus implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {long count = (long) context.getJobDetail().getJobDataMap().get("count");System.out.println("当前执行,第" + count + "次");context.getJobDetail().getJobDataMap().put("count", ++count);}
}
JobDetail job = JobBuilder.newJob(JobStatus.class).withIdentity("statusJob", "group1").usingJobData("count", 1L).build();

输出结果:

当前执行,第1次
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
当前执行,第2次
当前执行,第3次

Trigger

定时启动/关闭

Trigger 可以设置任务的开始结束时间, Scheduler 会根据参数进行触发。

Calendar instance = Calendar.getInstance();
Date startTime = instance.getTime();
instance.add(Calendar.MINUTE, 1);
Date endTime = instance.getTime();// 3.构建Trigger实例
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")// 开始时间.startAt(startTime)// 结束时间.endAt(endTime).build();

在 job 中也能拿到对应的时间,并进行业务判断

public void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务执行。。。");System.out.println(context.getTrigger().getStartTime());System.out.println(context.getTrigger().getEndTime());
}

运行结果:

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
1633149326723
任务执行。。。
Sat Oct 02 12:35:26 CST 2021
Sat Oct 02 12:36:26 CST 2021
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.

SimpleTrigger

这是比较简单的一类触发器,用它能实现很多基础的应用。使用它的主要场景包括:

  1. 在指定时间段内,执行一次任务

最基础的 Trigger 不设置循环,设置开始时间。

Quartz - 任务调度框架整合使用相关推荐

  1. Quartz任务调度框架

    Quartz 基本概念及原理 作为一个优秀的开源调度框架,Quartz 具有以下特点: 1.强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求: 2. 灵活的应用方式,例如支持任务 ...

  2. Quartz任务调度框架之最全Quartz系统参数配置详解

    我们通常是通过quartz.properties属性配置文件(默认情况下均使用该文件)结合StdSchedulerFactory 来使用Quartz的.StdSchedulerFactory 会加载属 ...

  3. (转)Java任务调度框架Quartz入门教程指南(四)Quartz任务调度框架之触发器精讲SimpleTrigger和CronTrigger、最详细的Cron表达式范例...

    http://blog.csdn.net/zixiao217/article/details/53075009 Quartz的主要接口类是Schedule.Job.Trigger,而触发器Trigge ...

  4. 阿里P8架构师谈:Quartz调度框架详解、运用场景、与集群部署实践

    以下将分别从Quartz架构简介.集群部署实践.Quartz监控.集群原理分析详解Quartz任务调度框架. Quartz简介 Quartz是Java领域最著名的开源任务调度工具,是一个任务调度框架, ...

  5. (转)Quartz任务调度(1)概念例析快速入门

    http://blog.csdn.net/qwe6112071/article/details/50991563 Quartz框架需求引入 在现实开发中,我们常常会遇到需要系统在特定时刻完成特定任务的 ...

  6. Quartz-2.2.1 任务调度框架在Java项目中的使用实例

    < Quartz-2.2.1 任务调度框架在Java项目中的使用实例 > 本实例是基于Quartz 2.2.1 版本为中心,也是目前最新的Quartz任务调度框架. 目前在 J2EE 项目 ...

  7. Spring整合定时任务调度框架Quartz实

    Spring整合定时任务调度框架Quartz实战 定时的任务处理在程序开发中应用的相当普遍,之前一直使用JDK的Timer类库来做任务调度功能不是很方便,因为它不能像cron服务那样可以指定具体年.月 ...

  8. 任务调度框架Quartz用法指南(超详细)

    前言 项目中遇到一个,需要 客户自定任务启动时间 的需求.原来一直都是在项目里硬编码一些定时器,所以没有学习过. 很多开源的项目管理框架都已经做了Quartz的集成.我们居然连这么常用得东西居然没有做 ...

  9. 任务调度框架Quartz用法指南

    前言 项目中遇到一个,需要客户自定任务启动时间 的需求.以往都是在项目中直接硬编码一些定时器,趁着这次机会将quartz的相关知识记录下来. Quartz是OpenSymphony开源组织在Job s ...

最新文章

  1. JSP怎么将表单提交到对应的servlet
  2. dell系统重装后无法进入系统_笔记本电脑常见故障开机无法进入系统
  3. android 自定义图片上传,android自定义ImageView仿图片上传示例
  4. php json csv,比JSON更简单,随便记数据的CSV介绍,以及PHP解析方法-csv文件怎么打开...
  5. 面试必会系列 - 3.1 Redis知识点大汇总(数据类型,内存模型,持久化,缓存击穿,集群,一致性哈希等等)
  6. delphi 获取java控件位置_delphi的IdFTP控件函数怎么调用
  7. 联想e431笔记本更改硬盘模式bios设置的详细教程
  8. 20-10-025-安装-KyLin-2.6.0-单机版安装(MAC官网下载)成功
  9. 8VC Venture Cup 2016 - Final Round (Div. 2 Edition) C. XOR Equation 数学
  10. angular源码分析 摘抄 王大鹏 博客 directive指令及系列
  11. 数据库课程设计实验报告--图书馆管理系统
  12. 实验九 TCP 协议分析实验
  13. ADP-L610-Arduino
  14. 云服务器快速建网站_安装BT宝塔面板和wordpress
  15. IDEA运行web项目及乱码处理
  16. 标准化和归一化 超全详解
  17. DART Karaoke Author1.35消除原唱人声的方法制作伴奏
  18. 多个空格的正则表达式
  19. ansible角色部署mysql主从复制
  20. 【大讲堂】进行精细化交通设计,我们该怎么做?

热门文章

  1. 怎么用CMD命令进入D盘
  2. 【通信原理 入坑之路】—— 数字载波传输系统 之 2PSK(二进制相移键控)2ASK(二进制幅度键控)的超详细分析
  3. 大数据技术主要包含哪些技术
  4. 多节点CDN缓存加速系统wdcdn2.2版本发布(20111115)
  5. 我所体验的HP金牌售后服务
  6. 新闻发布系统——用例图知识,温故知新
  7. vue.js之定义组件和子父组件数据传递及函数的相互调用
  8. 光学背投屏幕安装方法的技术建议
  9. 电池容量与放电时间的关系
  10. 第一章 SQL谓词的概述(一)