初识定时任务

news2024/9/23 3:27:55

了解定时任务

我们在开发系统的时候,常常会遇到需要定时的去执行一些业务,例如:定时备份数据库、定时生成报告、定时发送通知、定时批处理等各种自动化操作。

那此时我们就需要通过使用定时任务来完成这些业务需求。并且在日常的开发中定时任务可以提高系统的效率、自动化重复性操作,极大程度上减少了人工工作量。

定时任务种类

常见的定时任务分别有TimerScheduledThreadPoolExecutor(定时任务线程池),Spring TaskQuartzelastic-job……

在这么多的定时任务中,基本上都是两种理论基础实现的,分别是:小顶堆算法时间轮算法
其中TimerScheduledThreadPoolExecutor(定时任务线程池),Spring Task都是基于小顶堆算法实现的
Quartzelastic-job包括还有一些更为复杂的定时任务大部分都是基于时间轮算法实现的

(PS:Spring Task 中的@Scheduled注解严格意义上并不能说是基于小顶堆算法@Scheduled主要是依赖于Spring框架中的ThreadPoolExecutorTaskScheduler作为默认的任务调度器实现。它会根据指定的任务触发规则,将定时任务封装成一个Runnable,然后提交给线程池执行。但是TaskScheduler的底层实现是ThreadPoolTaskScheduler,它使用了ScheduledThreadPoolExecutor作为线程池。所以说它虽然没有直接使用小顶堆算法,但是底层使用了基于小顶堆算法ScheduledThreadPoolExecutor,我这边就把他归为小顶堆了)

接下来就开始介绍小顶堆

小顶堆

了解小顶堆之前,我们首先要了解

是一种特殊的树,只要满足以下两个条件,它就是一个堆:

  • 是一颗完全二叉树
  • 中某个节点的值总是不大于(或不小于)其父节点的值

其中,根节点最大的堆叫做大顶堆,根节点最小的对叫做小顶堆

满二叉树:所有层都达到最大节点数
在这里插入图片描述

完全二叉树:除了最后一层外其他层达到最大节点数,且最后一层节点都靠左排列

在这里插入图片描述
完全二叉树最适合用数组作为存储,因为它的节点都是紧凑的,并且只有最后一层节点数不满

在这里插入图片描述
为什么0节点不存储数据呢?
这是为了让我们可以更快更方便的去找到它的父节点(只需要将其下标除2),例如5的父节点就是5/2=2,6的父节点就是6/2=3,它们父节点的位置一目了然。

那我们的定时任务和这个堆又有什么关系呢?

实际上我们的定时任务每一个任务(Job)都对应这我们堆里的一个节点,就相当于每个节点都存放着一个Job。

那Job是如何存放的呢,难道是随便放吗?
实际上是Job的存放顺序是基于我们小顶堆的特性:最顶上的元素是最小的,这个就对应着我们定时任务的过期时间,最短的就放在最上面。当时间到了之后就直接去取对顶的元素执行就好了。堆顶元素执行之后,那下一次定时任务又改如何去拿呢?这个就需要取了解堆的存取元素的方法

插入元素

8字真言:尾部插入,然后上浮

为什么要从尾部插入,从顶部插入不行吗?

答:如果从顶部插入的话,如果顶部存在其他元素,就需要将所有的元素都往后移一位,而从尾部插入元素的话就不存在移位的操作。

插入元素后不一定满足堆的特性,为了继续满足堆的特性,我们就需要堆化。

样例:
往这个堆里插入元素2,我们把它放在9的后面,但是此时它并不满足(中某个节点的值总是不大于(或不小于)其父节点的值)这个条件,于是我们就需要将其进行堆化
在这里插入图片描述
在完全二叉树中,插入的节点与它的父节点相比,如果比父节点小,就交换他们的位置,交换后再比较再交换,直到它比父节点大为止。
这就是插入元素时进行的堆化,也叫自下而上的堆化

删除元素

!记住只能删除堆顶的元素

尾部(最大的元素)放到堆顶,然后下沉

如果小顶堆中堆顶存储是最小的元素,这时候我们把它删除会怎么样呢?

删除元素后,我们需要继续满足堆的特性,首先先把最后一个元素移到根节点的位置,这个就满足了第一个条件(完全二叉树),之后就是满足另一个父节点大于子节点的条件,于是我们就需要进行堆化。

示例:

在这里插入图片描述
在完全二叉树中,把最后一个节点放到堆顶,然后与左右子节点中最小的节点交换位置依次往下,直到比左右子节点都小为止(或者没有子节点)。
这就是删除元素时进行的堆化,也叫自上而下的堆化。

这就是小顶堆理论的具体实现逻辑,接下来我们看时间轮算法

时间轮算法

时间轮算法其实就是由链表或者数组实现的:while-true-sleep遍历数组,每个下标放置一个链表,链表节点放置任务,遍历到了就取出执行

很多人会好奇,为什么有了小顶堆又要用时间轮取实现呢?

实际上小顶堆是有弊端的,例如删除顶堆元素,如果此时我们的节点数过多,就需要进行大量的下沉操作,而我们定时任务的执行又是一个很平凡的时间,这样就会很耗费性能。
并且还有一个问题,例如顶堆的任务执行之后,按小顶堆的理论是需要将最尾端的节点放到顶端再一步一步进行下沉,此时就会出现一个问题:例如今天是1号,我尾端的任务是3号才执行,那我有必要把尾端的节点放到顶部再一步一步比对下沉吗?
这两种情况都会导致大量的性能浪费

所以此时就需要时间轮算法

简述

每个数组下标代表一个时间单位,例如小时或秒,而下标中存储的是在该时间单位内需要执行的任务。通过不断地轮转时间轮,将任务按照时间的先后顺序放入对应的槽位中。当时间轮转到某个槽位时,就执行该槽位上的所有任务
我在网上找了找了一张时间轮的图片(这看一眼应该就理解了)
在这里插入图片描述

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

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

相关文章

【从删库到跑路】一文带你明白MySQL数据库的 事务 操作

🎊专栏【MySQL】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 文章目录 🍔事务⭐简介⭐普通操作——不使用事务&#x1f3…

深入流行推荐引擎第一部分:推荐系统基础

深入流行推荐引擎第一部分:推荐系统基础 1. 推荐引擎及其类型什么是推荐引擎?基于内容的推荐(Content-Based Recommendations)协作推荐(Collaborative Recommendations)混合动力推荐(Hybrid Rec…

【stability.ai】SDXL:改进高分辨率图像合成的潜在扩散模型

github:https://github.com/Stability-AI/stablediffusion 试用: https://clipdrop.co/stable-diffusion https://dreamstudio.ai/ 介绍 近年来,深度生成建模在自然语言、音频和视觉媒体等各个数据领域取得了巨大的突破。本文将重点关注视…

计算机网络 day4 IP地址的两部分-A、B、C、D、E五类IP地址-私有地址-子网掩码-DNA服务器-域名解析服务

目录 三创网络拓扑结构图: 普通家庭网络拓扑结构图:(也可以直接使用 子母路由器 (母:无线路由器)(子:信号放大器、中继器)) 网络层:&#xff0…

一篇文章让你搞懂指针笔试题(加深对指针的理解)

指针笔试题 笔试题1 #include<stdio.h> int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));//程序的结果是什么&#xff1f;return 0; }给定一个数组a&#xff0c;当我们取地址a的时候&#xff0c…

基于stm32单片机的智能门禁系统设计

一.硬件方案 基于stm32单片机的智能门禁系统设计的整体电路主要由采用STM32F103单片机&#xff0c;4*4矩阵按键电路&#xff0c;电子锁继电器驱动电路&#xff0c;开锁LED指示灯&#xff0c;LCD1602显示屏电路&#xff0c;蜂鸣器报警电路&#xff0c;RFID感应电路&#xff0c;…

如何查看 当前安装的vue版本

目录 1 实现 1 实现 要查看当前安装的 Vue 版本&#xff0c;可以使用以下方法&#xff1a; 在终端或命令提示符中运行以下命令&#xff1a; vue --version如果你使用的是 Vue CLI 创建的项目&#xff0c;可以在项目的根目录中找到 package.json 文件。在该文件中&#xff0c…

【CSS】悬浮动画

文章目录 效果展示代码实现 效果展示 代码实现 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>一颗不甘坠落的流星</title></head><style type"text/css">.bth {/* 添加背景颜色 */backgr…

2023-7-7-第十三式模板方法模式

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

代码随想录算法训练营第60天/最后一天 | 84.柱状图中最大的矩形

今日任务 目录 84.柱状图中最大的矩形 - Hard 84.柱状图中最大的矩形 - Hard 题目链接&#xff1a;力扣-84. 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够…

Android之Handler分析与理解

Android中的Handler是一个用于处理消息和线程间通信的机制。它可以将Runnable对象或Message对象发送到特定的线程中进行处理。 使用Handler的主要目的是在不同的线程之间进行通信&#xff0c;特别是在后台线程中执行一些任务后&#xff0c;将结果发送到UI线程进行更新。 流程图…

pearsonr 报错:numpy.float64 can not be interpreted as an integer

【1】 模型求出pred&#xff0c;pearsonr(pred,true&#xff09; 出现以下报错&#xff1a; 【2】解释&#xff1a; 当在计算皮尔逊相关系数&#xff08;Pearson correlation coefficient&#xff09;时出现"numpy.float64 can not be interpreted as an integer"的…

7.7~7.8学习总结

StringBuider&#xff1a;线程不安全&#xff0c;效率高 StringBuffer&#xff1a;线程安全&#xff0c;效率低&#xff1b; 用法举例&#xff1a; class TWC {public static void main(String []args){StringBuilder sbnew StringBuilder("小麻子爱吃粑粑");Syst…

C语言学习(三十六)---文件操作

上节内容中&#xff0c;我们学习了练习了动态内存的练习题&#xff0c;并且学习了柔性数组的相关内容&#xff0c;大叫要好好掌握&#xff0c;今天&#xff0c;我们将学习文件操作的相关内容&#xff0c;这部分内容实际上很多&#xff0c;我们以点代面&#xff0c;好了&#xf…

windows已有mysql的情况下 mysql8 安装

安装前先停掉本地已有的mysql服务https://dev.mysql.com/downloads/mysql/ 下载mysql压缩包解压创建 my.init 文件 [mysqld] port 3307 basedirF:\mysql-8.0.33-winx64\mysql-8.0.33-winx64 datadirF:\mysql-8.0.33-winx64\mysql-8.0.33-winx64\data max_connections200 cha…

3.3.内存的学习,pinnedmemory,内存效率问题

目录 前言1. Memory总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习精简 CUDA 教程-内存模型&#xff0c;pinned memory&am…

2023.7.08

#include "widget.h"void Widget::my_slot() {if((edit1->text()"admin")&&(edit2->text()"123456")){qDebug()<<"登陆成功";emit jump();close();}else{qDebug()<<"登陆失败";} }void Widget::b…

OSPFv2基础02_工作原理

目录 1.OSPF接口状态 2.OSPF邻居状态 2.1 OSPF邻居状态类型 2.2 广播网络OSPF邻接关系建立 3.Router ID&#xff08;路由器ID&#xff09;选举 4.DR和BDR选举 4.1 为什么引入DR和BDR&#xff1f; 4.2 DR和BDR的作用 4.3 DR和BDR选举过程 4.4 DR和BDR选举原则 5.OSPF路…

基于单片机指纹考勤系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;利用指纹采集模块存储打卡信息&#xff1b;12864显示当前考勤信息&#xff0c;时间 &#xff1b;如果迟到 语音播报 您已迟到&#xff1b;按键进行注册指纹、删除指纹、设置当前时间和签到时间、查询打卡等&#xff1b;具有掉电保存…

【YOLOv7调整detect.py】1.调整检测框粗细,2.设定标签颜色,3.只显示与标签数目相同的检测结果

目录 1. 调整检测框粗细2. 设定标签颜色3. 只显示与标签数目相同的检测结果 1. 调整检测框粗细 在detect.py中按住CtrlF检索line_thickness定位过去&#xff0c;在129行左右&#xff0c;更改line_thickness的大小即可&#xff0c;例如改为line_thickness3 2. 设定标签颜色 在…