Quartz中禁止并发机制源码级解析
文章目录
Quartz进行任务调度时通常会要求一个任务禁止并发执行,此时只需要在Job类上面添加一个注解@DisallowConcurrentExecution即可。在保存到数据库里面时,对应QRTZ_JOB_DETAILS表中的IS_NONCONCURRENT字段的值为1(true)。那么这里是怎么控制的呢?
在Quartz项目搭建与任务执行源码分析中详细介绍一个正常流程过程中涉及的表和状态的变化过程。总结的表格如下
| 表名 | scheduleJob | acquireNextTriggers | triggersFired | triggeredJobComplete |
|---|---|---|---|---|
| QRTZ_TRIGGERS | WAITING | (CAS)ACQUIRED | WAITING | WAITING |
| QRTZ_FIRED_TRIGGERS | ACQUIRED | EXECUTING |
而对于禁止并发的任务,其状态则如下所示
| 表名 | scheduleJob | acquireNextTriggers | triggersFired | triggeredJobComplete |
|---|---|---|---|---|
| QRTZ_TRIGGERS | WAITING | (CAS)ACQUIRED | BLOCKED | WAITING |
| QRTZ_FIRED_TRIGGERS | ACQUIRED | EXECUTING |
- 调度任务在查询待触发任务时,如果同时查出来一个任务对应的多个触发器,只有第一个有效(通过
acquiredJobKeysForNoConcurrentExec集合保证唯一性)
org.quartz.impl.jdbcjobstore.JobStoreSupport#acquireNextTrigger
Set<JobKey> acquiredJobKeysForNoConcurrentExec = new HashSet<JobKey>();
// ... 其他代码省略// If trigger's job is set as @DisallowConcurrentExecution, and it has already been added to result, then// put it back into the timeTriggers set and continue to search for next trigger.JobKey jobKey = nextTrigger.getJobKey();JobDetail job = getDelegate().selectJobDetail(conn, jobKey, getClassLoadHelper());if (job.isConcurrentExectionDisallowed()) {if (acquiredJobKeysForNoConcurrentExec.contains(jobKey)) {continue; // next trigger} else {acquiredJobKeysForNoConcurrentExec.add(jobKey);}}
- 任务触发时,将不支持并发机制的触发器的状态由 WAITING -> BLOCKED,这样调度线程查询待触发任务时便不会满足条件(调度任务只会查询WAITING状态的触发器)
org.quartz.impl.jdbcjobstore.JobStoreSupport#triggersFired
if (job.isConcurrentExectionDisallowed()) {state = STATE_BLOCKED;force = false;try {getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),STATE_BLOCKED, STATE_WAITING);getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),STATE_BLOCKED, STATE_ACQUIRED);getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),STATE_PAUSED_BLOCKED, STATE_PAUSED);} catch (SQLException e) {throw new JobPersistenceException("Couldn't update states of blocked triggers: "+ e.getMessage(), e);}
}
- 任务执行完毕,会将触发器的状态修改回来 BLOCKED -> WAITING
org.quartz.core.QuartzScheduler#notifyJobStoreJobComplete
执行org.quartz.spi.JobStore#triggeredJobComplete方法
if (jobDetail.isConcurrentExectionDisallowed()) {getDelegate().updateTriggerStatesForJobFromOtherState(conn,jobDetail.getKey(), STATE_WAITING,STATE_BLOCKED);getDelegate().updateTriggerStatesForJobFromOtherState(conn,jobDetail.getKey(), STATE_PAUSED,STATE_PAUSED_BLOCKED);signalSchedulingChangeOnTxCompletion(0L);
}
除了以上地方,在Quartz启动时,org.quartz.impl.jdbcjobstore.JobStoreSupport#recoverJobs首先会将一些阻塞的任务都修改为WAITING,防止系统崩溃导致任务未执行完而来不及恢复禁止并发任务的状态。
// update inconsistent job states
int rows = getDelegate().updateTriggerStatesFromOtherStates(conn,STATE_WAITING, STATE_ACQUIRED, STATE_BLOCKED);rows += getDelegate().updateTriggerStatesFromOtherStates(conn,STATE_PAUSED, STATE_PAUSED_BLOCKED, STATE_PAUSED_BLOCKED);getLog().info("Freed " + rows+ " triggers from 'acquired' / 'blocked' state.");
另外在项目启动、新增触发器、定时任务补偿等所有涉及数据库操作Trigger中都会执行org.quartz.impl.jdbcjobstore.JobStoreSupport#storeTrigger操作,而其中都会检查状态,checkBlockedState.
if (job.isConcurrentExectionDisallowed() && !recovering) { state = checkBlockedState(conn, job.getKey(), state);
}if (existingTrigger) {getDelegate().updateTrigger(conn, newTrigger, state, job);
} else {getDelegate().insertTrigger(conn, newTrigger, state, job);
}
而checkBlockedState中,就会根据是否禁止并发并判断是否任务已经执行(通过selectFiredTriggerRecordsByJob查询QRTZ_FIRED_TRIGGERS表中是否有数据)返回BLOCKED状态,org.quartz.impl.jdbcjobstore.JobStoreSupport#checkBlockedState。
/*** Determines if a Trigger for the given job should be blocked. * State can only transition to STATE_PAUSED_BLOCKED/BLOCKED from * PAUSED/STATE_WAITING respectively.* * @return STATE_PAUSED_BLOCKED, BLOCKED, or the currentState. */
protected String checkBlockedState(Connection conn, JobKey jobKey, String currentState)throws JobPersistenceException {// State can only transition to BLOCKED from PAUSED or WAITING.if ((!currentState.equals(STATE_WAITING)) &&(!currentState.equals(STATE_PAUSED))) {return currentState;}try {List<FiredTriggerRecord> lst = getDelegate().selectFiredTriggerRecordsByJob(conn,jobKey.getName(), jobKey.getGroup());if (lst.size() > 0) {FiredTriggerRecord rec = lst.get(0);if (rec.isJobDisallowsConcurrentExecution()) { // OLD_TODO: worry about failed/recovering/volatile job states?return (STATE_PAUSED.equals(currentState)) ? STATE_PAUSED_BLOCKED : STATE_BLOCKED;}}return currentState;} catch (SQLException e) {throw new JobPersistenceException("Couldn't determine if trigger should be in a blocked state '"+ jobKey + "': "+ e.getMessage(), e);}}
从上面可以看到,基本上在整个操作触发器的生命周期,都会考虑当前任务是否禁止并发操作,通过QRTZ_FIRED_TRIGGERS表是否有数据判断任务是否执行、不支持并发机制的任务在执行时将QRTZ_TRIGGERS中的状态改为BLOCKED以避免再次被触发。
相关文章:
Quartz中禁止并发机制源码级解析
文章目录 Quartz进行任务调度时通常会要求一个任务禁止并发执行,此时只需要在Job类上面添加一个注解DisallowConcurrentExecution即可。在保存到数据库里面时,对应QRTZ_JOB_DETAILS表中的IS_NONCONCURRENT字段的值为1(true)。那么…...
为什么从公有云迁移到私有云的越来越多?
随着云计算的快速发展,越来越多的组织开始考虑将其IT基础设施从公有云迁移到私有云。这种转变背后存在着一系列的原因和动机,下面我们将探讨一些常见的迁移原因。 首先,数据安全和隐私是许多组织选择私有云的主要原因之一。在公有云中&#…...
用shell实现MySQL分库分表操作
#!/bin/bash mysql_cmd-uroot -p123 #定义变量保存密码 exclude_dbinformation_schema|performance_schema|sys #数据库 bak_path/backup/db #备份路径 mysql ${mysql_cmd} -e show databases -N | egrep -v "${exclude_db}" > dbname while read line do …...
php 适配器模式
一,适配器模式,属于结构设计模式的一种,用于将一个类的接口转换成客户期望的接口。 1,目标接口(Target Interface):是客户期望的接口,定义了客户要调用的方法。 2,适配器…...
Scratch Blocks自定义组件之「下拉图标」
一、背景 由于自带的下拉图标是给水平布局的block使用,放在垂直布局下显得别扭,而且下拉选择后回修改image字段的图片,这让我很不爽,所以在原来的基础上稍作修改,效果如下: 二、使用说明 (1&am…...
Robot Framweork之UI自动化测试---分层设计
Robot Framework 的分层思想是一种测试设计和代码组织的模式,它将测试用例的实现和测试执行逻辑分离,以提高测试的可维护性、可读性和可扩展性。 一、分层思想 在实际项目中,一般分为三层:元素层,流程层,用…...
MySQL8.0/8.x更新用户密码命令
authentication_string 这是Mysql8.0新做出的修改,在旧版本中使用的是password()函数。 2,在网上找到的mysql忘记密码的解决方案中,大多会使用 UPDATE user SET authentication_string12345 WHERE userroot; 来直接将密码改成12345࿰…...
【MySQL】下载安装以及SQL介绍
1,数据库相关概念 以前我们做系统,数据持久化的存储采用的是文件存储。存储到文件中可以达到系统关闭数据不会丢失的效果,当然文件存储也有它的弊端。 假设在文件中存储以下的数据: 姓名 年龄 性别 住址 张三 23 男 北京…...
算法题--二叉树(二叉树的最近公共祖先、重建二叉树、二叉搜索树的后序遍历序列)
目录 二叉树 题目 二叉树的最近公共祖先 原题链接 解析 二叉搜索树的最近公共节点 核心思想 答案 重建二叉树 题目链接 解析 核心思想 答案 二叉搜索树的后序遍历序列 原题链接 解析 核心思想 答案 二叉树 该类题目的解决一般是通过节点的遍历去实现&#x…...
mysql的基础面经-索引、事务
1 聚簇索引 1 和主键索引的关系 2 和非聚簇索引的关系,其叶子节点存储的是聚簇索引中的主键 3 索引覆盖机制使得非聚簇索引不用回表二次查询 2 举一个使用索引覆盖的例子 我的项目中没有使用到覆盖索引,但是可以举一个例子,比如我直接为年…...
Windows下双网卡配置静态路由,实现内外网同时使用
怎么样设置双网卡?内网外网两个网络这么同时连接? 接下来听好了,赶紧动手 情况描述: 我使用的Windows10电脑,支持双网卡工作 目前我工作需要使用的使用内网,但是又需要使用外网,需要同时使用&a…...
Spring整合Mybatis、Spring整合JUnit
🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaweb 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 Spring整合 一、Spring整合Mybatis1.1 整合Mybatis&#x…...
Devops系统中jira平台迁移
需求:把aws中的devops系统迁移到华为云中,其中主要是jira系统中的数据迁移,主要方法为在华为云中建立一套 与aws相同的devops平台,再把数据库和文件系统中的数据迁移,最后进行测试。 主要涉及到的服务集群CCE、数据库mysql、弹性文件服务SFS、数据复制DRS、弹性负载均衡ELB。 迁…...
【雕爷学编程】MicroPython动手做(29)——物联网之SIoT
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...
LAXCUS分布式操作系统引领科技潮流,进入百度首页
信息源自某家网络平台,以下原样摘抄贴出。 随着科技的飞速发展,分布式操作系统做为通用基础平台,为大数据、高性能计算、人工智能提供了强大的数据和算力支持,已经成为了当今计算机领域的研究热点。近日,一款名为LAXCU…...
Linux--按行读取数据:fgets
函数定义: char *fgets(char *s,int size,FILE *stream); S是指接受数据缓冲区,用于存放stream里读取的数据 size是指缓冲区的大小 返回值为NULL表明读取失败,反之读取成功...
express学习笔记5 - 自定义路由异常处理中间件
修改router/index.js,添加异常处理中间件 *** 自定义路由异常处理中间件* 注意两点:* 第一,方法的参数不能减少* 第二,方法的必须放在路由最后*/ router.use((err, req, res, next) > {console.log(err);const msg (err &…...
filebeat介绍
1、filebeat概述 Filebeat是用于转发和集中日志数据的轻量级传送工具。Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash或kafka进行索引 1.1 Filebeat两个主要组件 prospector 和 harvester。 prospector&a…...
使用SSM框架实现个人博客管理平台以及实现Web自动化测试
文章目录 前言1. 项目概述2. 项目需求2.1功能需求2.2 其他需求2.3 系统功能模块图 3. 开发环境4. 项目结构5. 部分功能介绍5.1 数据库密码密文存储5.2 统一数据格式返回5.3 登录拦截器 6. 项目展示7. 项目测试7.1 测试用例7.2 执行部分自动化测试用例 前言 在几个月前实现了一…...
【深度学习】MAT: Mask-Aware Transformer for Large Hole Image Inpainting
论文:https://arxiv.org/abs/2203.15270 代码:https://github.com/fenglinglwb/MAT 文章目录 AbstractIntroductionRelated WorkMethod总体架构卷积头Transformer主体Adjusted Transformer Block Multi-Head Contextual Attention Style Manipulation Mo…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
