时间轮设计

目录

基本概念

函数定义

函数实现与测试

测试1结果如下

测试2结果如下


基本概念

时间轮 是一种 实现延迟功能(定时器)巧妙算法。如果一个系统存在大量的任务调度,时间轮可以高效的利用线程资源来进行批量化调度。把大批量的调度任务全部都绑定时间轮上,通过时间轮进行所有任务的管理,触发以及运行。能够高效地管理各种延时任务,周期任务,通知任务等。

这几张图是了解了解用的,可能看不懂,用以解决mudo服务器中高并发性能的要求的

weak_ptr了解一下下

函数定义

#include <iostream>
#include <stdint.h>
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:uint64_t _id;         // 定时器任务对象uint32_t _timeout;    // 定时任务的超时时间TaskFunc _task_cb;    // 定时器要执行的定时任务ReleaseFunc _release; // 用于删除TimerWheel中保存的定时器对象信息
public:TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb) : _id(id), _timeout(delay), _task_cb(cb) {}~TimerTask(){_task_cb();_release();}void SetRelease(const ReleaseFunc &cb) { _release = cb; }
};class TimerWheel
{
private:using WeakTask = std::weak_ptr<TimerTask>;using PtrTask = std::shared_ptr<TimerTask>;int _tick;                                      // 当前的的秒针,走到哪里哪里就释放执行int _capacity;                                  // 表盘最大数量 -- 其实就是最大延迟时间std::vector<std::vector<PtrTask>> _wheel;std::unordered_map<uint64_t, WeakTask> _timers; // 用weak_ptr来构造出新的shared_ptr用来计数,不过后续要记得释放
public:TimerWheel() : _capacity(60), _tick(0), _wheel(_capacity) {}void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb); // 添加定时任务void TimerRefresh(uint64_t id);                                 // 刷新/延迟定时任务
};

函数实现与测试

#include <iostream>
#include <stdint.h>
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>
#include <unistd.h>using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:uint64_t _id;         // 定时器任务对象uint32_t _timeout;    // 定时任务的超时时间bool _canceled;       // false-表示没有被取消,true-表示被取消TaskFunc _task_cb;    // 定时器要执行的定时任务ReleaseFunc _release; // 用于删除TimerWheel中保存的定时器对象信息
public:TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb) : _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}~TimerTask(){if (_canceled == false)_task_cb();_release();}void Cancel() { _canceled = true; }void SetRelease(const ReleaseFunc &cb) { _release = cb; }uint32_t DelayTime() { return _timeout; } // 返回时间
};class TimerWheel
{
private:using WeakTask = std::weak_ptr<TimerTask>;using PtrTask = std::shared_ptr<TimerTask>;int _tick;     // 当前的的秒针,走到哪里哪里就释放执行int _capacity; // 表盘最大数量 -- 其实就是最大延迟时间std::vector<std::vector<PtrTask>> _wheel;std::unordered_map<uint64_t, WeakTask> _timers; // 用weak_ptr来构造出新的shared_ptr用来计数,不过后续要记得释放
private:void RemoveTimer(uint64_t id){auto it = _timers.find(id);if (it != _timers.end()){_timers.erase(it);}}public:TimerWheel() : _capacity(60), _tick(0), _wheel(_capacity) {}void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb) // 添加定时任务{PtrTask pt(new TimerTask(id, delay, cb));                      // 实例化定时任务对象pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id)); // 第0个位置是隐藏的this指针。再把任务id绑定进去int pos = (_tick + delay) % _capacity;_wheel[pos].push_back(pt);_timers[id] = WeakTask(pt);}// 刷新/延迟定时任务void TimerRefresh(uint64_t id){// 通过保存的定时器对象的weak_ptr构造一个shared_ptr出来, 添加到轮子中auto it = _timers.find(id);if (it == _timers.end()){return; // 没找到定时任务, 没法刷新,没法延迟}PtrTask pt = it->second.lock(); // lock获取weak_ptr管理的对象对应的shared_ptrint delay = pt->DelayTime();    // 获取到了初始的延迟时间int pos = (_tick + delay) % _capacity;_wheel[pos].push_back(pt);}void TimerCancel(uint64_t id){auto it = _timers.find(id);if (it == _timers.end()){return; // 没找到定时任务, 没法刷新,没法延迟}PtrTask pt = it->second.lock(); // 当还没有过期才进行取消if(pt) pt->Cancel();}// 这个函数应该每秒钟被执行一次,相当于秒钟向后走了一步void RunTimerTask(){_tick = (_tick + 1) % _capacity;_wheel[_tick].clear(); // 清空指定位置的数组,就会把数组中保存的所有管理定时器对象的shared_ptr释放掉.从而执行函数}
};// 以下是测试
class Test
{
public:Test() { std::cout << "构造" << std::endl; }~Test() { std::cout << "析构" << std::endl; }
};void DelTest(Test *t)
{delete t;
}int main()
{TimerWheel tw;Test *t = new Test();tw.TimerAdd(888, 5, std::bind(DelTest, t));for (int i = 0; i < 5; i++){sleep(1);tw.TimerRefresh(888); // 刷新定时任务tw.RunTimerTask();    // 向后移动秒针std::cout << "刷新了一下定时任务,重新需要5s钟后才会销毁\n";}// tw.TimerCancel(888); // 取消定时任务的测试while (1){sleep(1);std::cout << "------------------------\n";tw.RunTimerTask(); // 向后移动秒钟}return 0;
}

测试1结果如下

达到预期

测试2结果如下

将下列代码放开

测试2结果如下

取消成功,达到预期

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

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

相关文章

React16源码: React中的resetChildExpirationTime的源码实现

resetChildExpirationTime 1 &#xff09;概述 在 completeUnitOfWork 当中&#xff0c;有一步比较重要的一个操作&#xff0c;就是重置 childExpirationTimechildExpirationTime 是非常重要的一个时间节点&#xff0c;它用来记录某一个节点的子树当中&#xff0c;目前优先级最…

C++提高编程——STL:string容器、vector容器

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…

数据结构:堆与堆排序

目录 堆的定义&#xff1a; 堆的实现&#xff1a; 堆的元素插入&#xff1a; 堆元素删除&#xff1a; 堆初始化与销毁&#xff1a; 堆排序&#xff1a; 堆的定义&#xff1a; 堆是一种完全二叉树&#xff0c;完全二叉树定义如下&#xff1a; 一棵深度为k的有n个结点的二…

ffmpeg使用及java操作

1.文档 官网: FFmpeg 官方使用文档: ffmpeg Documentation 中文简介: https://www.cnblogs.com/leisure_chn/p/10297002.html 函数及时间: ffmpeg日记1011-过滤器-语法高阶&#xff0c;逻辑&#xff0c;函数使用_ffmpeg gte(t,2)-CSDN博客 java集成ffmpeg: SpringBoot集成f…

科技云报道:金融大模型落地,还需跨越几重山?

科技云报道原创。 时至今日&#xff0c;大模型的狂欢盛宴仍在持续&#xff0c;而金融行业得益于数据密集且有强劲的数字化基础&#xff0c;从一众场景中脱颖而出。 越来越多的公司开始布局金融行业大模型&#xff0c;无论是乐信、奇富科技、度小满、蚂蚁这样的金融科技公司&a…

深度学习如何弄懂那些难懂的数学公式?是否需要学习数学?

经过1~2年的学习&#xff0c;我觉得还是需要数学有一定认识&#xff0c;重新捡起高等数学、概率与数理、线代等这几本&#xff0c;起码基本微分方程、求导、对数、最小损失等等还是会用到。 下面给出几个链接&#xff0c;可以用于平时充电学习。 知乎上的&#xff1a; 机器学…

计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

git merge和git rebase区别

具体详情 具体常见如下&#xff0c;假设有master和change分支&#xff0c;从同一个节点分裂&#xff0c;随后各自进行了两次提交commit以及修改。随后即为change想合并到master分支中&#xff0c;但是直接git commit和git push是不成功的&#xff0c;因为分支冲突了【master以…

上位机图像处理和嵌入式模块部署(流程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;传统图像处理的方法&#xff0c;一般就是pccamera的处理方式。camera本身只是提供基本的raw data数据&#xff0c;所有的…

基于ADAS的车道线检测算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 图像预处理 4.2 车道线特征提取 4.3 车道线跟踪 5.完整工程文件 1.课题概述 基于ADAS的车道线检测算法,通过hough变换和边缘检测方法提取视频样板中的车道线&#xff0c;然后根据车道线的弯曲情况…

Linux/Mac 命令行工具 tree 开发项目结构可以不用截图了 更方便 更清晰 更全

tree 是一个命令行工具&#xff0c;用于以树形结构显示文件系统目录的内容。它可用于列出指定目录下的所有文件和子目录&#xff0c;以及它们的层次关系。tree 命令在许多操作系统中都可用&#xff0c;包括Unix、Linux和macOS。 效果如下&#xff1a; 一、安装 linux # De…

Prometheus+Grafana监控Mysql数据库

Promethues Prometheus https://prometheus.io Prometheus是一个开源的服务监控系统&#xff0c;它负责采集和存储应用的监控指标数据&#xff0c;并以可视化的方式进行展示&#xff0c;以便于用户实时掌握系统的运行情况&#xff0c;并对异常进行检测。因此&#xff0c;如何…

Spring Boot3整合knife4j(swagger3)

目录 1.前置条件 2.导依赖 3.配置 1.前置条件 已经初始化好一个spring boot项目且版本为3X&#xff0c;项目可正常启动。 作者版本为3.2.2最新版 2.导依赖 knife4j官网&#xff1a; Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)http…

R语言简介

1.R语言 R语言是一种数学编程语言&#xff0c;主要用于统计分析、绘图和数据挖掘。 2.R语言特点 免费、开源&#xff0c;兼容性好&#xff08;Windows、MacOS或Linux)。具有多种数据类型&#xff0c;如向量、矩阵、因子、数据集等常用数据结构。多用于交互式数据分析&#x…

股权众筹模式介绍(下)

3、线上线下两段式投资 对于已经成成立并运营的企业来说&#xff0c;由于《证券法》明确规定&#xff0c;向“不特定对象发行证券”以及“向特定对象发行证券累计超过200人”的行为属于公开发行证券&#xff0c;必须通过证监会核准&#xff0c;由证券公司承销。这些规定限定了…

RTDETR 引入 UniRepLKNet:用于音频、视频、点云、时间序列和图像识别的通用感知大卷积神经网络 | DRepConv

大卷积神经网络(ConvNets)近来受到了广泛研究关注,但存在两个未解决且需要进一步研究的关键问题。1)现有大卷积神经网络的架构主要遵循传统ConvNets或变压器的设计原则,而针对大卷积神经网络的架构设计仍未得到解决。2)随着变压器在多个领域的主导地位,有待研究ConvNets…

小程序商城 免 费 搭 建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c

java SpringCloud版本b2b2c鸿鹄云商平台全套解决方案 使用技术&#xff1a; Spring CloudSpring BootMybatis微服务服务监控可视化运营 B2B2C平台&#xff1a; 平台管理端(包含自营) 商家平台端(多商户入驻) PC买家端、手机wap/公众号买家端 微服务&#xff08;30个通用…

Unity中URP下的SimpleLit的 BlinnPhong高光反射计算

文章目录 前言一、回顾Blinn-Phong光照模型1、Blinn-Phong模型&#xff1a; 二、URP下的SimpleLit的 BlinnPhong1、输入参数2、程序体计算 前言 在上篇文章中&#xff0c;我们分析了 URP下的SimpleLit的 Lambert漫反射计算。 Unity中URP下的SimpleLit的 Lambert漫反射计算 我…

Java基于沙箱环境实现支付宝支付

一、支付宝沙箱环境介绍 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境&#xff0c;开发者在沙箱环境中调用接口无需具备所需的商业资质&#xff0c;无需绑定和开通产品&#xff0c;同时不会对生产环境中的数据造成任何影响。合理使用沙箱环境&#xff0c;可以…

Android14实战:调整A2DP音量曲线(五十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…