Quartz任务调度框架

news2024/9/21 0:42:40

文章目录

  • 前言
  • 一、介绍
  • 二、使用步骤
    • 1.创建maven工程,添加依赖
    • 2.创建任务
    • 3.启动任务
  • 三、基本实现原理
    • 1. Scheduler任务调度器
    • 2. Triggers触发器
      • 2.1 SimpleTrigger
      • 2.2 CronTirgger
    • 3. Misfire策略
    • 4 任务Job
      • 4.1 Job
      • 4.2 JobDetail
      • 4.3 JobDataMap


前言

最近跟的一个系统需要实时监控主机的应用进程以及存储空间等,实时生成告警提醒,这就需要在规定的时间去触发消息提醒功能,在这里主要也是用到了Quartz来调度任务的。


一、介绍

Quartz作为 Spring 默认的调度框架,与 Spring 集成实现灵活可配置的调度功能,此外其支持多种调度方法,应用方式灵活,并具有分布式和集群能力。
应用场景:

  • 驱动流程:比如在确定时间后根据任务完成情况触发一个警告并通知
  • 系统维护:在具体时间点调度一个数据从数据库转到xml文件中
  • 在应用中提供消息提醒服务

二、使用步骤

1.创建maven工程,添加依赖

下载quartz的jar包,导入依赖

<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.2</version>
</dependency>

2.创建任务

(1)创建一个类实现quartz提供的Job接口
(2)实现Job接口定义的execute方法,定义任务逻辑

代码如下(示例):

public class MyJob implements Job {
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	public void execute(JobExecutionContext jobExecutionContext)
	throws JobExecutionException {
		//执行任务的逻辑
		String time = sdf.format(new Date());
		System.out.println("~~~~~"+time);
	}
}

3.启动任务

使用任务调度器Scheduler进行任务管理

  • 启动任务
  • 暂停任务
  • 继续任务
  • 停止任务
package com.qfedu.job;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
public class QuartzTest {
	public static void main(String[] args) {
	    try {
			//1.创建Quartz的任务调度器
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			//2.创建触发器:定义了任务调度的时机(延时、循环、定时...)
			// simpleScheduleBuilder对象表示任务的触发规则
			SimpleScheduleBuilder simpleScheduleBuilder =
			SimpleScheduleBuilder.simpleSchedule()
			.withIntervalInSeconds(3)
			.withRepeatCount(10);
			SimpleTrigger trigger = TriggerBuilder.newTrigger()
			.withIdentity("trigger1", "group1")// withIdentity 设置trigger唯一表示
			.startAt(new Date(System.currentTimeMillis() + 5000))// startAt 设置首
			次触发时间
			.withSchedule(simpleScheduleBuilder)// withSchedule 设置触发器的触发规则
			.build(); // 通过TriggerBuilder对象,构造Trigger对象
			//3.创建任务(JobDetail 用于封装具体的任务)
			JobDetail job = JobBuilder.newJob(MyJob.class).build();
			//将任务及触发器,绑定到任务调度
			scheduler.scheduleJob(job,trigger);
			//启动任务
			scheduler.start()
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	 }
}

三、基本实现原理

  • scheduler:任务调度器(执行调度的控制器)
  • trigger:触发器,用于定义任务调度时间规则
  • job:任务,即被调度的任务
    在这里插入图片描述

1. Scheduler任务调度器

Scheduler任务调度器由SchedulerFactory 工厂创建,主要提供了以下两种工厂实现:

  • DirectSchedulerFactory(使用较麻烦,需要进行编码配置)
  • StdSchedulerFactory(✔)

Scheduler 主要有三种:

  • RemoteMBeanScheduler
  • RemoteScheduler
  • StdScheduler(✔)
    创建任务调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

2. Triggers触发器

用于定义调度时间的元素,例如按照什么时间规则去执行任务
主要包括四种类型(这里只详细介绍SimpleTrigger和CronTrigger)

  • DateIntervalTrigger 日期周期的规则的触发器
  • NthIncludedDayTrigger 排除指定时间周期和日期的触发器

2.1 SimpleTrigger

使用简单便捷。可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行并且以制定的间隔重复执行若干次。
适用场景:

  1. 延时任务:当用户提交订单之后启动任务,延时30min检查订单状态,如果未支付则取消订单
    释放库存
  2. 循环任务:每个指定的时间周期执行一次任务,任务可以循环(可以无限循环、可以循环指
    定的次数、还可以循环执行到指定的时间点)
  3. 定时任务:在指定的时间点调度执行任务
    规则:
  4. 重复次数,可以是0、正整数,以及常量SimpleTrigger.REPEAT_INDEFINITELY
  5. 重复的间隔,必须是0,或者long型的正数,表示毫秒。注意,如果重复间隔为0,trigger将会以重
    复次数并发执行(或者以scheduler可以处理的近似并发数)。
  6. endTime属性的值会覆盖设置重复次数的属性值;比如,你可以创建一个trigger,在终止时间之前
    每隔10秒执行一次,你不需要去计算在开始时间和终止时间之间的重复次数,只需要设置终止时间
    并将重复次数设置为REPEAT_INDEFINITELY。
//指定时间触发,每隔10秒执行一次,重复10次:
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
							.withIntervalInSeconds(10)
							.withRepeatCount(10);
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
				.withIdentity("trigger3", "group1")
				.startAt(myTimeToStartFiring) //指定触发的时间
				.withSchedule(simpleScheduleBuilder) //指定触发器的时间规则
				.forJob(myJob)
				.build();

2.2 CronTirgger

使用cron表达式定义触发任务的时间规则,通常比SimpleTrigger更有用,如果需要基于日历的概念而不是按照SimpleTrigger的精确指定间隔进行重新启动的作业启动计划。使用CronTrigger可以指时间表,例如“每周五中午”或“每个工作日和上午9:30”,甚至“每周一至周五上午9:00至10点之间每5分钟”和1月份的星期五“。和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止计划。

// 通过cron表达式定义触发任务的时间规则
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/3 * * * * ?");
//触发器
CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger()
			.withIdentity("cronTrigger1","group1")
			.startAt( DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND) )//设置首次执行任务的时间
			.withSchedule( cronScheduleBuilder ) //将时间规则设置给触发器
			.endAt(DateBuilder.dateOf(22,0,0) ) //设置任务终止的时间
			.build();

简单介绍一下Cron表达式:
由七个子表达式组成的字符串(最后一个年份可省略)

Seconds Minutes Hours Day-of-Month Month Day-of-Week Year
   秒      分    时        日期      月份    星期几   年份
//示例
#每5分钟就会触发一次
“0 0/5 * * *?”
#每5分钟触发一次,分钟后10秒(即上午1010分,上午10:05:10等)。
“10 0/5 * * *?”

3. Misfire策略

Misfire当已经绑定到调度器Scheduler的触发器及任务在执行的过程中,因Scheduler出现故障停止了、或者线程池中没有充足的线程执行到期的任务,从而导致Trigger触发周期到了但是任务没有执行的情况。
对于所有类型的Trigger,Quartz都为其指定了默认的定义其恢复之后的执行策略——MISFIRE_INSTRUCTION_SMART_POLICY(立即执行misfire的任务,然后继续按计划往后执行)

  1. SimpleTrigger的Misfire策略
#当资源可用时立即执行所有misfire的任务,执行到设置的endTime剩余的周期次数
MISFIRE_INSTRUCTION_FIRE_NOW
#不会判断misfire,当资源可用时立即执行所有misfire的任务,然后按照原计划执行
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
#立即执行第一次misfire任务,修改startTime为当前时间,按照原来的时间间隔执行下一次任务(总次数不变)
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
# 立即执行第一次misfire任务,修改startTime为当前时间,按照原来的时间间隔执行下一次任务(剩下的任务)
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
# 不会立即执行任务,等到下一次计划时间到达时开始执行,忽略已经发生的misfire任务
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
# 不会立即执行任务,等到下一次计划时间到达时开始执行,忽略已经发生的misfire任务
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT

//示例
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
			.withIntervalInSeconds(3).repeatForever()
			//.withMisfireHandlingInstructionFireNow()
			//.withMisfireHandlingInstructionIgnoreMisfires()
			//.withMisfireHandlingInstructionNextWithExistingCount()
			//.withMisfireHandlingInstructionNextWithRemainingCount()
			//.withMisfireHandlingInstructionNowWithExistingCount()
			.withMisfireHandlingInstructionNowWithRemainingCount();
SimpleTrigger trigger = TriggerBuilder.newTrigger()
			.withIdentity("trigger1","group1")
			.withSchedule(simpleScheduleBuilder) .build();
  1. CronTrigger的Misfire策略
# 立即执行所有的misfire任务,然后继续按计划执行
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
# 发生的misfire的任务都会被忽略,从当前时间按照原计划执行
MISFIRE_INSTRUCTION_DO_NOTHING
#立即执行第一个发生misfire的任务,忽略其他misfire的任务,然后按照原计划继续执行
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 

//示例
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
		.cronSchedule("0 0 12 ? * MON#1 2022")
		//.withMisfireHandlingInstructionIgnoreMisfires()
		//.withMisfireHandlingInstructionDoNothing()
		.withMisfireHandlingInstructionFireAndProceed();
CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger()
		.withIdentity("cronTrigger1","group1")
		.withSchedule( cronScheduleBuilder )
		.build();

4 任务Job

4.1 Job

Job表示被调度的任务,在任务调度的业务开发中,quartz提供了Job接口,我们自定义执行任务类实现此Job接口,在execute方法中完成业务的执行。

  • 两种类型的Job:无状态的和有状态的
    有状态的job不能被并行执行,只有上一次触发的任务被执行完之后才能触发下一次执行。
  • 两种属性:volatility 和 durability
    其中 volatility 表示任务 是否被持久化 到数据库存储,而 durability 表示在没有 trigger 关联的时候任务是否被保留。两者都是在值为 true 的时候任务被持久化或保留。

4.2 JobDetail

用于封装Job实例所包含的属性

//创建任务(JobDetail 用于封装具体的任务)
JobDetail job = JobBuilder.newJob(MyJob.class)
	.withIdentity("job1","group1") //设置任务的标识
	.build();

4.3 JobDataMap

包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据。

//将job加入到scheduler之前,在构建Trigger、JobDetail时,可以将数据放入JobDataMap
//1.创建Quartz的任务调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2.创建触发器
SimpleScheduleBuilder simpleScheduleBuilder =
	SimpleScheduleBuilder.simpleSchedule()
	.withIntervalInSeconds(3)
    .withRepeatCount(10)
    .withMisfireHandlingInstructionNextWithRemainingCount();
SimpleTrigger trigger = TriggerBuilder.newTrigger()
	.withIdentity("trigger1", "group1")
	.withSchedule(simpleScheduleBuilder)
	.usingJobData("key1","value1") //设置Trigger参数
	.build();
//3.创建任务(JobDetail 用于封装具体的任务)
JobDetail job = JobBuilder.newJob(MyJob.class)
	.withIdentity("job1","group1")
	.usingJobData("key2","value2") //设置JobDetail参数
	.build();
scheduler.scheduleJob(job,trigger);
scheduler.start();
//在Job执行过程中,可以从JobDataMap中取出数据
public class MyJob implements Job {
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	public void execute(JobExecutionContext jobExecutionContext)
	throws JobExecutionException {
		//执行任务的逻辑
		// 通过execute方法的JobExecutionContext参数获取触发器、JobDetail绑定的参数
		// 1.获取trigger中传递的参数
		JobDataMap jobDataMap1 = jobExecutionContext.getTrigger().getJobDataMap();
		String value1 = (String) jobDataMap1.get("key1");
		// 2.获取JobDetail中传递的参数
		JobDataMap jobDataMap2 =
		jobExecutionContext.getJobDetail().getJobDataMap();
		String value2 = (String) jobDataMap2.get("key2");
		String time = sdf.format(new Date());
		System.out.println("~~~~~"+time+"\t"+value1+"\t"+value2);
	}
}

学习地址:
java涛哥:Quartz任务调度框架

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

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

相关文章

洞见数据价值,激活组织活力,让决策更精准的智慧地产开源了

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。通过计算机视觉和…

Sql查询优化--索引设计与sql优化(包含慢查询定位+explain解释计划+左匹配原则+索引失效)

本文介绍了数据库查询的索引优化方法&#xff0c;依次介绍了慢查询语句定位方法、索引设计与sql语句优化方法&#xff0c;并介绍了左匹配原则和索引失效的场景&#xff0c;最后介绍了explain执行计划要怎么看以调整检验索引设计是否生效和效率情况&#xff0c;创新介绍了如何以…

AWS api数据信息获取(boto3)

GitHub - starsliao/TenSunS: &#x1f984;后羿 - TenSunS(原ConsulManager)&#xff1a;基于Consul的运维平台&#xff1a;更优雅的Consul管理UI&多云与自建ECS/MySQL/Redis同步Prometheus/JumpServer&ECS/MySQL/Redis云监控指标采集&Blackbox站点监控维护&漏…

4家国产数据库上市公司:最好的盈利1个亿,最惨亏8000w

目前国产数据库xc目录中大概有11家公司&#xff0c;其中多家公司已经上市了&#xff0c;且公布了最新的半年报&#xff01; 这里尝试分析一下几家国产数据库上市公司的发展潜力和情况。 达梦数据库 达梦数据库作为国产数据库第一股&#xff0c;业绩增长还是一如既往的猛&…

【零知识证明】通读Tornado Cash白皮书(并演示)

1 Protocol description 协议描述有以下功能&#xff1a; 1.insert&#xff1a;向智能合约中存入资金&#xff0c;通过固定金额的单笔交易完成&#xff0c;金额由N表示&#xff08;演示时用1 ETH&#xff09; 2.remove&#xff1a;从智能合约中提取资金&#xff0c;交易由收…

ncnn之yolov5(7.0版本)目标检测pnnx部署

一、pnxx介绍与使用 pnnx安装与使用参考&#xff1a; https://github.com/pnnx/pnnxhttps://github.com/Tencent/ncnn/wiki/use-ncnn-with-pytorch-or-onnxhttps://github.com/Tencent/ncnn/tree/master/tools/pnnx 支持python的首选pip&#xff0c;否则就源码编译。 pip3 …

Webpack打包常见问题及优化策略

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介Webpack打包常见问题及优化策略1. 引言2. Webpack打包常见问题2.1 打包时间过长问题描述主要原因 2.2 打包体积过大问题描述主要原因 2.3 依赖包版本冲突问题描述主要原因 2.4 动态导入和代码拆分问题问题描述主要原因 2.5 文件路径…

C++系列-继承方式

继承方式 继承的语法继承方式&#xff1a;继承方式的特点继承方式的举例 继承可以减少重复的代码。继承允许我们依据另一个类来定义一个类&#xff0c;这使得创建和维护一个应用程序变得更容易。基类父类&#xff0c;派生类子类&#xff0c;派生类是在继承了基类的部分成员基础…

编程效率进阶:打造你专属的 Git 别名与 PyCharm 完美结合

在日常开发中&#xff0c;Git 是我们不可或缺的工具。掌握常用 Git 命令可以帮助我们更高效地进行版本控制&#xff0c;但随着命令的复杂性增加&#xff0c;记住所有命令变得困难。这时&#xff0c;Git 别名的设置就显得尤为重要。此外&#xff0c;许多开发者使用 PyCharm 作为…

【Android自定义控件】Kotlin实现滚动效果的数字加减控件

前言 因业务上的需要&#xff0c;在APP中点餐时要有商品数目增减操作&#xff0c;数目增减的过程中有翻动的动画效果展现。在Android中有多种方式可以实现&#xff0c;本篇文章记录通过自定义View结合控件的平移动画相结合来实现此需求。 需求分析 根据上图分析控件的实现过程以…

Pillow:一个强大的图像处理Python库

我是东哥&#xff0c;一个热衷于探索Python世界的自媒体人。今天&#xff0c;我要向大家介绍一个在Python图像处理领域中不可或缺的库——Pillow。如果你对图像处理感兴趣&#xff0c;或者正在寻找一个简单易用的库来处理图片&#xff0c;那么Pillow绝对是你的不二之选。 基本…

【前端】代码Git提交规范之限制非规范化提交信息

需求背景 在我们目前的前端项目中&#xff0c;我们采用 git 作为版本控制工具。使用 git 管理项目意味着我们经常需要提交代码。当我们执行 git commit -m "描述信息" 命令时&#xff0c;我们被要求提供一个描述信息。现在使用约定式规范提交&#xff0c;和Commitiz…

用纯 div 实现一个选中和未选中状态

在现代网页设计中&#xff0c;利用 div 元素自定义样式&#xff0c;可以让界面更具有吸引力。通过一些简单的 CSS 样式和布局技巧&#xff0c;可以轻松实现交互自然的选中和未选中效果&#xff0c;而不需要依赖传统的 input 元素。 举个 &#x1f330; HTML <body><…

金融POS三层密钥体系 银行卡网络安全系统

银行卡网络安全系统的三层密钥体系 银行卡网络安全系统的三层密钥体系为金融POS系统提供了高度安全的密钥管理。这个体系从上到下分为三层&#xff1a;系统密钥、主密钥、和工作密钥。每一层密钥都负责保护下一层密钥的安全性&#xff0c;确保系统整体的安全性。 三层密钥体系…

[图解]强化自测题解析-总纲(一)01 这属于什么工作流

1 00:00:00,680 --> 00:00:05,350 今天我们开始来解析一些强化自测题 1 00:00:01,100 --> 00:00:03,980 因为现在强化自测题本身 2 00:00:05,010 --> 00:00:06,720 我们出得已经比较多了 3 00:00:07,700 --> 00:00:12,570 自测题是用来测试我们的开发人员 4 00…

华为OD机试真题 - 字符串排序(Python/JS/C/C++ 2024 D卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、…

QT教程-十六,QT中如何解析JSON

一&#xff0c;对json的初步认识 &#xff08;这里我们主要说明最常用的&#xff0c;以一个宏观的概念来说一下&#xff09;&#xff0c;json是一种数据格式&#xff0c;作用就是便于传递信息&#xff0c;我们可以按其结构和对应关系&#xff0c;拿到我们想要的数据。其主要结构…

【专题】2024全球电商消费电子市场研究报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37552 在如今数字经济蓬勃发展的大环境下&#xff0c;电商行业正以前所未有的迅猛之势&#xff0c;对全球商业版图进行着深刻的重塑。据 Stocklytics 发布的有关全球电商市场价值及未来增长趋势的专项调查报告显示&#xff0c;2024…

团队比赛时如何给小组记分?

在团队比赛中&#xff0c;确保每个小组的成绩和排名准确无误是组织者的重要任务。云分组小程序提供了一个便捷的“项目记分”功能&#xff0c;帮助您轻松管理比赛记分过程。以下是如何使用该功能进行团队比赛记分的详细步骤。一、准备工作 1. 打开云分组小程序。 2. 点击“我的…

SQLi-LABS靶场51-55通过攻略

less-51 1.判断注入点 ?sort1 加上单引号会引起报错 2.判断闭合方式 ?sort1-- 可以闭合成功 3.查询数据库名 使用报错注入查询 ?sort1 and updatexml(1,concat(1,database()),1)-- 4.查询数据库的所有表 ?sort1 and updatexml(1,concat(1,(select group_concat(tab…