定时任务-xxl-job

一. 为什么定时任务可以定时执行

定时任务可以定时执行的原理是通过操作系统提供的定时器实现的。

以下是定时任务能够准时执行的基本原理和相关技术:
操作系统的调度器: 操作系统(如Linux、Windows等)内部都有一个调度器,负责管理和调度各种进程和任务。这个调度器通常基于时间片(time slice)或者其他调度算法来分配CPU时间给不同的任务。
定时器和时钟: 操作系统会维护一个时钟系统,它通常是一个硬件计时器或者软件计时器,用于定期触发中断或事件。基于这些时钟,操作系统能够准确追踪时间,并在指定的时刻触发特定的任务。
定时任务的注册和管理: 在操作系统或者特定的任务调度器中,可以注册和管理定时任务。这些任务通常由操作系统或者相关的服务来执行,并在指定的时间点或时间间隔内触发执行。
精确时间的管理: 现代操作系统能够提供比较精确的时间管理,如毫秒级或者更高的精度,这使得定时任务可以按照预期的时间间隔或者具体的时间点执行。
持久化和可靠性: 对于需要持久化的定时任务,操作系统或者相关的任务调度器通常会保证在系统重启后能够恢复原有的调度状态,确保定时任务不会因为系统重启而中断。

二. 为什么Cron表达式可以定时执行

Cron表达式可以定时执行底层也是基于操作系统的定时器的机制。在常见的计算机操作系统中,都提供了一种定时器机制,可以设置定时器来触发某个操作或执行某个任务。在我们在系统中设置了一个Cron任务后,Cron服务会工具Cron表达式计算出任务下一次应该执行的时间点,并将这个时间点与当前时间点进行比较,如果当前时间点已经超过了任务的执行时间点,那么Cron服务会立即执行该任务;否则Cron服务会将任务的执行时间点记录下来,并在这个时间点到来时再执行任务。

在 Unix/Linux 系统中,Cron 服务通常是通过一个名为 cron 的系统服务来实现的。这个服务会周期性地检查系统中已经配置好的 crontab 文件,根据其中的配置信息来决定哪些任务应该被执行。

crontab 文件中包含了多条定时任务的配置信息,其中每条任务都由五个时间字段和一个命令行指令组成。这五个时间字段分别表示分钟、小时、日期、月份和星期几,cron 会根据这些时间信息来判断任务何时应该被执行。当定时器达到指定时间时,cron 会根据 crontab 文件中的配置信息,启动相应的命令行指令来执行任务。这样,定时任务就可以按照预定的时间定时执行了。

三. Java中实现定时任务的方式

1. java中原生特性(JDK自带的功能)实现定时任务:

Timer类和TimerTask类: Timer类是Java SE5之前的一个定时器工具类,可用于执行定时任务。TimerTask类则表示一个可调度的任务,通常通过继承该类来实现自己的任务,然后使用Timer.schedule()方法来安排任务的执行时间。

ScheduledExecutorService类: ScheduledExecutorService是Java SE5中新增的一个定时任务执行器,它可以比Timer更精准地执行任务,并支持多个任务并发执行。通过调用ScheduledExecutorService.schedule(或ScheduledExecutorService.scheduleAtFixedRate()方法来安排任务的执行时间。

DelayQueue: DelayQueue是一个带有延迟时间的无界阻塞队列,它的元素必须实现Delayed接口。当从DelayQueue中取出一个元素时,如果其延迟时间还未到达,则会阻塞等待,直到延迟时间到达。因此,我们可以通过将任务封装成实现Delaved接口的元素,将其放入DelayQueue中再使用一个线程不断地从DelayQueue中取出元素并执行任务,从而实现定时任务的调度。

2. 需要引入第三方框架实现定时任务方式:

Spring的@Scheduled注解: Spring框架提供了一个方便的定时任务调度功能,可以使用@Scheduled注解来实现定时任务。通过在需要执行定时任务的方法上加上@Scheduled注解,并指定执行的时间间隔即可。

Quartz框架: Quartz是一个流行的开源任务调度框架,它支持任务的并发执行和动态调度。通过创建JobDetail和Trigger对象,并将它们交给Scheduler进行调度来实现定时任务。

xxl-job: xxl-job是一款分布式定时任务调度平台,可以实现各种类型的定时任务调度,如定时执行Java代码、调用HTTP接口、执行Shel脚本等。xxl-job采用分布式架构,支持集群部署,可以满足高并发、大数据量的任务调度需求。

Elastic-Job: Elastic-Job是一款分布式任务调度框架,可以实现各种类型的定时任务调度,如简单任务、数据流任务、脚本任务、Spring
Bean任务等。Elastic-Job提供了丰富的任务调度策略可以通过配置cron表达式、固定间隔等方式实现定时任务调度。Elastic-Job支持分布式部署,提供了高可用性和灵活的扩展性,可以满足高并发、大数据量的任务调度需求,

3. java中原生特性(JDK自带的功能)实现定时任务与引入第三方框架实现定时任务区别:

java中原生特性实现定时任务,相比于xxl-job这种定时任务调度框架来说,原生特性实现起来简单,不用依赖第三方的调度框架和类库。方案更加轻量级。缺点是原生特性方案都是基于JVM内存的,需要把定时任务提前放进去,如果数据量太大的话,可能会导致OOM的问题;另外,基于JVM内存的方案,一旦机器重启了,里面的数据就都没有了,所以一般都需要配合数据库的持久化一起用,并且在应用启动的时候也需要做重新加载。

四. 实现一个定时任务,可以用什么数据结构和算法

1.小顶堆:可以使用小顶堆来管理定时任务,其中每个事件包含触发时间戳和要执行的任务信息。最先要触发的任务处于堆的根部,这样可以高效地找到最近触发的定时事件,并在触发时执行相应的任务。

小顶堆(Min Heap)是一种特殊的二又堆数据结构。对于堆中的任意节点i,其父节点的值小于等于节点i的值。换句话说,堆中的最小值总是位于堆的根节点上。
在定时器的实现中,每个定时事件可以表示为一个包含触发时间戳的数据结构。从堆顶不断取出需要执行的定时任务即可。在这里插入图片描述

2.时间轮算法:时间轮算法是一种时间管理算法,可以高效地处理定时任务。是一种用于处理定时任务和调度的常见算法。它把时间划分成若干个时间槽,并使用循环队列来存储在每个时间槽上触发的任务,从而避免了遍历整个定时事件集合的开销。
时间轮(TimingWheel)是一个 存储定时任务的环形队列,底层采用数组实现,数组中的每个元素可以存放一个定时任务列表(TimerTaskList)。TimerTaskList 是一个环形的双向链表,链表中的每一项表示的都是定时任务项(TimerTaskEntry),其中封装了真正的定时任务 TimerTask。

简单时间轮算法:
时间轮算法主要需要定义一个时间轮盘,在一个时间轮盘中划分出多个槽位,每个槽位表示一个时间段,这个段可以是秒级、分钟级、小时级等等。如以下就是把一个时间轮分为了60个时间槽,每一个槽代表一秒钟。

在这里插入图片描述
当我们有定时任务需要执行的时候,就把他们挂在到这些槽位中,这个任务将要在哪个槽位中执行,就把他挂在到哪个槽位的链表上。比如当前如果是0秒,那么要3秒后执行,那就挂在槽位为3的那个位置上。
缺点:这种时间轮存在一个问题,就是分了多少槽位,就只支持多少以内定时。

简单时间轮加round:
在时间轮中增加一个round的标识,标识运行的圈数,比如上面的60s的时间轮,如果我要200s之后运行,那么我在设置这个任务的时候,就把他的round设置为200/60=3,然后再把它放到200%60=20的这个槽位上。
有了这个round之后,每一次current移动到某个槽位时,检查任务的round是不是为0,如果不为0,则减一。这样时间轮转到第三圈时,round的值会变成0,再第四运行到current=20的时候,发现round=0了,那么就可以执行这个任务了。
缺点:round的检查过程,需要把所有任务都遍历一遍,效率不高。
在这里插入图片描述

分层时间轮:
专为大批量定时任务管理而生。比如要支持触发时间是一年的精度为秒级别的时间轮,如果单纯的用一个秒级的时间轮:3652460*60 这都三千多万个时间格了,造成大量资源开销。而分层的话,那么可分为四个层次,天级别的时间轮,小时级时间轮,分钟级时间轮,秒级时间轮,他们的时间格数分别为365,24,60,60,总时间格数只有365+24+60+60=509个。这样解决了上面两种时间轮的缺点。
在这里插入图片描述

3.链表(用的比较少):链表可以用于管理定时事件,每个节点包含触发时间戳和任务信息。链表中的节点按照触发时间戳从小到大排序,通过遍历链表,可以找到最近触发的定时事件并执行任务。

五.xxl-job怎么保证任务只会触发一次

xxl-job 作为一个定时任务调度工具,需要确保同一时间内同一任务只会在一个执行器上执行。这个特性对于避免任务的重复执行非常关键,特别是在分布式环境中,多个执行器实例可能同时运行相同的任务。这个特性被xxl-job描述为“调度一致性”,“调度中心”通过DB锁保证集群分布式调度的一致性,一次任务调度只会触发一次执行。

几个关键点:
任务调度器: xxl-job 的调度器负责按照设定的调度策略(如 cron表达式)定时触发任务执行。调度器确保在预定的时间点触发任务,避免任务重复触发。
执行器与任务执行状态管理: 执行器是实际执行任务逻辑的组件,它负责执行具体的任务代码。xxl-job会在任务执行前记录任务的执行状态,并在执行完成后更新任务状态,以确保同一个任务实例不会重复执行。
任务幂等性: 开发者需要在编写任务逻辑时考虑任务的幂等性,确保任务的多次执行不会产生错误结果或者重复操作。xxl-job 并未提供特定的JobScheduleHelper 类或方法来保证任务只会触发一次,而是通过任务的设计和调度管理来实现这一目标。
调度中心管理任务触发: xxl-job 的核心组件是调度中心,它负责管理注册的所有任务及其调度配置(如CRON表达式)。调度中心根据任务的执行时间点和配置,决定何时触发任务的执行。调度中心在XXL-JOB中负责管理所有任务的调度,当到达指定的执行时间点,调度中心会选择一个执行器实例来执行任务。
数据库锁确保任务唯一执行: 为了确保任务在同一时间点只会被触发一次执行,xxl-job 使用了数据库锁机制。具体来说,当调度中心准备触发某个任务时,它会尝试获取数据库中的锁。这些锁可以是行级锁或表级锁,用于控制对任务执行状态的并发访问。
JobScheduleHelper 协调任务调度: JobScheduleHelper 是 xxl-job 中负责协调任务调度逻辑的组件之一。它利用数据库锁基于数据的悲观锁实现的一个加锁过程,确保同一时间点只有一个执行器实例能够获取并执行特定任务。其他执行器实例在获取锁失败时会等待或重试,以避免重复执行。

六.xxl-job支持分片任务的实现原理:

分片任务非常适用于处理大数据的任务,其实就是可以将一个大任务划分为多个子任务并行执行来提高效率。

分片任务的实现原理主要包含以下几个核心步骤:
任务分配: 当一个分片任务被触发时,调度器会根据任务的分片参数决定需要多少个执行器参与任务。每个执行器或执行线程会接收到一个分片索引(shard index)和分片总数(shard total)。
分片参数: 分片索引(从0开始)标识了当前执行器处理的是哪一部分数据。分片总数告诉执行器总共有多少个分片。
并行执行: 每个执行器根据分配到的分片索引并行执行其任务。例如,如果一个任务被分为10个片,那么每个执行器可能负责处理10%的数据。
处理逻辑: 开发者在任务实现时需要根据分片索引和分片总数来调整处理逻辑,确保每个分片处理正确的数据段。
结果汇总: 分片执行完毕后,各个执行器的执行结果可以被独立处理,或者可以通过某种机制进行结果的汇总和整合。

当一个任务被分片任务调度的时候,会带着shardlndex和shardTotal两个参数过来,我们就可以解析这两个参数进行分片执行。
例子如下:

public ReturnT<String>orderTime0utExecute(){int shardIndex=XxlJobHelper.getShardIndex();int shardTotal =XxlJobHelper.getShardTotal();if(userId %shardTotal == shardIndex){// 执行任务System.out.println("执行任务:用户"+ userId);}else {//不执行任务System.out.println("用户"+userId +" 不执行任务");}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

electron 配置、打包 -报错解决

目录 一、配置途中遇到的问题&#xff1a; 二、 make 配置好后开始打包 三、Electron-builder 打包报错 一、配置途中遇到的问题&#xff1a; 1. 安装 yarn add electron -D 一直卡在这里失败 一直卡可以使用下面这个&#xff0c;然后再重新装依赖 1. 采用新的镜像地址 npm …

机械学习—零基础学习日志(高数22——泰勒公式理解深化)

核心思想&#xff1a;函数逼近 在泰勒的年代&#xff0c;如果想算出e的0.001次方&#xff0c;这是很难计算的。那为了能计算这样的数字&#xff0c;可以尝试逼近的思想。 但是函数又不能所有地方都相等&#xff0c;那退而求其次&#xff0c;只要在一个极小的范围&#xff0c;…

Modbus-RTU详解

目录 Modbus-RTU协议 帧结构示例 CRC16校验算法 CRC16算法的过程 modbus-rtu的使用 发送数据 接收数据 tcp网口完整实现modbus-rtu协议 使用NModbus4实现modbus-rtu协议 安装NModbus4库。 串口实现NModbus4 Modbus-RTU协议 Modbus RTU 协议是一种开放的串行协议&#xff0c;广…

GroupMamba实战:使用GroupMamba实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

26集 ESP32 AIchat启动代码分析-《MCU嵌入式AI开发笔记》

26集 ESP32 AIchat启动代码分析-《MCU嵌入式AI开发笔记》 这集我们分析代码如何组织起来&#xff0c;如何编译 先用sourceinsight把代码加进工程。 新建一个sourceinsight工程&#xff0c;把AI-CHAT代码加进来&#xff0c;之后把ESP IDF代码加进来&#xff0c;之后把ESP-ADF加…

大语言模型(LLM)文本预处理实战

大语言模型&#xff08;LLM&#xff09;文本预处理实战 文章目录 大语言模型&#xff08;LLM&#xff09;文本预处理实战2.1 理解词嵌入2.2 文本分词2.3 将 token 转换为 token ID2.4 添加特殊上下文 token2.5 字节对编码 (BytePair Encoding, BPE)2.6 使用滑动窗口进行数据采样…

sql注入部分总结和复现

一个端口对应一个服务 联合查询注入 所有的程序中&#xff0c;单双引号必须成对出现 需要从这个引号里面逃出来 在后面查询内容 ?id1 要查库名&#xff0c;表名&#xff0c;列名。但是联合查询要知道有多少列&#xff0c;所以通过order by 去查询 order by # 通过二分法…

Cartopy简介和安装

Cartopy 是一个开源免费的第三方 Python 扩展包&#xff0c;由英国气象办公室的科学家们开发&#xff0c;支持 Python 2.7 和 Python 3&#xff0c;致力于使用最简单直观的方式生成地图&#xff0c;并提供对 matplotlib 友好的协作接口。初学Cartopy&#xff0c;欢迎指正&#…

算法回忆录(3)

11. 假设有7个物品&#xff0c;它们的重量和价值如下表所示。若这些物品均不能被分割&#xff0c;且背包容量M&#xff1d;150&#xff0c;设计算法求解怎么装才能使得获取的价值最大&#xff1f;请写出伪代码。 #include <stdio.h>#define MAX_ITEMS 100 #define …

新手小白嵌入式单片机教程,ESP32

1.什么是ESP32。 ESP32是一款由乐鑫信息科技&#xff08;Espressif Systems&#xff09;推出的高度集成的低功耗系统级芯片&#xff08;SoC&#xff09;&#xff0c;它结合了双核处理器、无线通信、低功耗特性和丰富的外设&#xff0c;特别适用于各种物联网&#xff08;IoT&am…

Robot Operating System——深度解析单线程执行器(SingleThreadedExecutor)执行逻辑

大纲 创建SingleThreadedExecutor新增Nodeadd_nodetrigger_entity_recollectcollect_entities 自旋等待get_next_executablewait_for_workget_next_ready_executableTimerSubscriptionServiceClientWaitableAnyExecutable execute_any_executable 参考资料 在ROS2中&#xff0c…

python 爬虫入门实战——爬取维基百科“百科全书”词条页面内链

1. 简述 本次爬取维基百科“百科全书”词条页面内链&#xff0c;仅发送一次请求&#xff0c;获取一个 html 页面&#xff0c;同时不包含应对反爬虫的知识&#xff0c;仅包含最基础的网页爬取、数据清洗、存储为 csv 文件。 爬取网址 url 为 “https://zh.wikipedia.org/wiki/…

数据结构:基于顺序表实现通讯录系统(含源码)

目录 一、前言 二、各个功能的实现 2.1 初始化通讯录 2.2 添加通讯录数据 2.3 查找通讯录数据 2.4 删除通讯录数据 2.5 修改通讯录数据 2.6 展示通讯录数据​编辑 2.7 销毁通讯录数据 三、添加菜单和测试 四、完整源码 sxb.h sxb.c contact.h contact.c test.c 一、前…

【隐私计算篇】混淆电路之深入浅出

入门隐私计算的阶段&#xff0c;一般都会涉及对于混淆电路的学习&#xff0c;这是因为混淆电路是多方安全计算中的基础密码原语&#xff0c;也是隐私保护中重要的技术。为了帮助更好地理解混淆电路的原理&#xff0c;今天对其进行原理以及相关优化手段进行解析和分享。 1. 混淆…

不同角色路由权限配置(六)

一、启用方式 配置开启config/config.ts。同时需要 src/access.ts 提供权限配置 export default {access: {},// access 插件依赖 initial State 所以需要同时开启initialState: {}, };这里以扩展的路由配置为例&#xff0c;配置只有admin权限才能查看的页面 1、在src/acces…

前端web开发HTML+CSS3+移动web(0基础,超详细)——第3天

目录 一&#xff0c;列表-无序和有序的定义列表 二&#xff0c;表格-基本使用与表格结构标签 三&#xff0c;合并单元格 四&#xff0c;表单-input标签 五&#xff0c;表单-下拉菜单 六&#xff0c;表单-文本域 七&#xff0c;表单-label标签 八&#xff0c;表单-按钮 …

【已解决】页面操作系统功能,诡异报错500nginx错误

【已解决】页面操作系统功能&#xff0c;诡异报错500nginx错误&#xff0c;后台没有任何报错信息 不知道啥原因 清理了浏览器缓存 也没有效果 还有一个表现情况&#xff0c;同样的操作&#xff0c;有时可以又是不行 因为报错ng的代理问题&#xff0c;检查了ng配置 后续经过同…

【C/C++】C语言和C++实现Stack(栈)对比

我们初步了解了C&#xff0c;也用C语言实现过栈&#xff0c;就我们当前所更新过的有关C学习内容以栈为例子&#xff0c;来简单对比一下C语言和C。 1.C中栈的实现 栈的C语言实现在【数据结构】栈的概念、结构和实现详解-CSDN博客 &#xff0c;下面是C实现的栈&#xff0c; 在St…

OD C卷 - 多线段数据压缩

多段 线 数据压缩 &#xff08;200&#xff09; 如图中每个方格为一个像素&#xff08;i&#xff0c;j&#xff09;&#xff0c;线的走向只能水平、垂直、倾斜45度&#xff1b;图中线段表示为(2, 8)、&#xff08;3,7&#xff09;、&#xff08;3, 6&#xff09;、&#xff08…

学习STM32(2)--STM32单片机GPIO应用

目录 1 引 言 2 实验目的 3 实验内容 3.1掌握STM32F103的GPIO控制 3.1.1 GPIO的分组 3.1.2 GPIO的常用功能 3.1.3 STM32单片机GPIO位结构 3.1.4 STM32单片机GPIO工作模式 3.1.5 STM32的GPIO 输出-点亮LED编程要点 使用GPIO时&#xff0c;按下面步骤进行&#xff1…