当前位置: 首页 > news >正文

延时任务定时器的实现

定时器是什么?

组织和管理大量延时任务的模块

定时器解决了什么问题?

在不过度占用线程的情况下,高效处理定时任务。

定时器如何解决问题?

1.通过数据结构组织大量延时任务

2.对将要超时的延时任务进行触发。

定时器的数据结构选择

红黑树:红黑树是一个有序二叉树,且插入和删除操作的复杂度小于AVL树,可以将任务按触发顺序进行排序,每次选择超时任务只需选择最左节点即可。

最小堆:最小堆中根节点永远是最小的,同样可以将任务按触发顺序加入到最小堆中,每次选择根节点即可

时间轮:将超时任务按顺序放入时间轮中,针对当前时间轮中的时间指针做偏移。

定时器的触发机制

利用 IO 多路复用最后一个参数(超时参数)

使用IO 多路复用系统调用如select/poll/epoll最后一个参数,将定时器的触发时机与网络事件的触发时机相同,从而将定时器何时触发交给IO多路复用

while (!quit) {int timeout = get_nearest_timer() - now();if (timeout < 0) timeout = -1;int nevent = epoll_wait(epfd, ev, nev,
timeout);for (int i=0; i<nevent; i++) {// ... 处理网络事件}// 处理定时事件update_timer();
}
// 网络事件和定时事件在不同线程中处理
void * thread_timer(void *thread_param) {init_timer();while (!quit) {update_timer();sleep(t);}clear_timer();return NULL;
}
pthread_create(&pid, NULL, thread_timer,
&thread_param);

timerfd

利用 timerfd,将定时检测作为 IO 多路复用当中的事件进行处理;

#include <sys/timerfd.h>
// 创建一个定时器文件描述符,可以像网络 IO 一样,将这个 fd
交由 IO 多路复用来管理
int timerfd_create(int clockid, int flags);
// 设置一个触发时间,IO 多路复用将会检测这个过期事件,然后
通知应用程序定时事件就绪
int timerfd_settime(int fd, int flags,const struct itimerspec
*new_value,struct itimerspec
*old_value);

定时器实现

#pragma once// #include <sys/epoll.h>
// #include <unistd.h>
#include <map>
#include <functional>
#include <chrono>
//定时任务节点
class TimerNode {
public:friend class Timer;TimerNode(uint64_t timeout, std::function<void()> callback): timeout_(timeout), callback_(std::move(callback)) {}
private:int id;uint64_t timeout_;std::function<void()> callback_;
};class Timer {
public:static Timer* GetInstance() {static Timer instance;return &instance;}static uint64_t GetCurrentTime() {using namespace std::chrono;return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();}//添加定时任务TimerNode* AddTimeout(uint64_t diff, std::function<void()> cb) {auto node  =  new TimerNode(GetCurrentTime() + diff, std::move(cb));//如果节点超时时间小于红黑树的最大节点的超时时间,则使用插入if (timer_map_.empty() || node->timeout_ < timer_map_.rbegin()->first) {auto it = timer_map_.insert(std::make_pair(node->timeout_, std::move(node)));return it->second;//否则直接插入到红黑树的最右端} else {auto it = timer_map_.emplace_hint(timer_map_.crbegin().base(), std::make_pair(node->timeout_, std::move(node)));return it->second;}};//删除节点void DelTimeout(TimerNode* node) {auto it = timer_map_.equal_range(node->timeout_);for (auto iter = it.first; iter != it.second; ++iter) {if (iter->second == node) {timer_map_.erase(iter);break;}}}// 获取延时任务还需等待的时间int WaitTime() {auto iter = timer_map_.begin();if (iter == timer_map_.end()) {return -1;}uint64_t diff = iter->first - GetCurrentTime();return diff > 0 ? diff : 0;}//处理延时任务void HandleTimeout() {auto iter = timer_map_.begin();while (iter != timer_map_.end() && iter->first <= GetCurrentTime()) {iter->second->callback_();iter = timer_map_.erase(iter); // 删除已处理的定时器}}
private:std::multimap<uint64_t, TimerNode*> timer_map_;//使用mutimap存储每个定时任务,同一时间可能有多个任务Timer() = default;Timer(const Timer&) = delete;Timer& operator=(const Timer&) = delete;Timer(Timer&&) = delete;Timer& operator=(Timer&&) = delete;~Timer() {for (auto& pair : timer_map_) {delete pair.second;}}
};#define TimerInstance Timer::GetInstance

https://github.com/0voice

http://www.dtcms.com/a/339499.html

相关文章:

  • Python 新工具 uv
  • 读《精益数据分析》:营收(Revenue)—— 设计可持续盈利模式
  • 【ASP.NET Core】ASP.NET Core中间件解析
  • sfc_os!SfcQueueValidationRequest函数分析之sfc_os!IsFileInQueue
  • 关闭VSCode Markdown插件在Jupyter Notebook中的自动预览
  • 在linux系统中下载Andconda
  • windows电脑对于dell(戴尔)台式的安装,与创建索引盘,系统迁移到新硬盘
  • Vim 编辑器使用指南
  • Java I/O 模型精讲:从传统BIO到高性能NIO与AIO
  • uv与conda的区别及选择指南
  • Linux软件编程:进程与线程(进程(消息队列、共享内存、信号灯))
  • 决策树二-泰坦尼克号幸存者
  • 微服务集训整理
  • AI赋能市场拓展:从智能潜力洞察到渠道精准深耕,解锁商业增长新蓝海
  • 【Proteus仿真】【51单片机】基于51单片机密码锁
  • 优秘企业智脑 AISEO 实战:如何通过多模态大模型提升搜索引擎排名?附 3 大行业案例
  • pytorch学习笔记-argparse的使用(加更版)
  • 基于SpringBoot+Vue的写真馆预约管理系统(邮箱通知、WebSocket及时通讯、协同过滤算法)
  • 哪些仪器适合对接电子实验记录本,哪些不适合?
  • Java 11中的Collections类详解
  • Web安全攻防基础
  • 什么是IP隔离?一文讲清跨境电商/海外社媒的IP隔离逻辑
  • JVM对象创建和内存分配
  • 2025年12大AI测试自动化工具
  • 基礎複分析習題6.級數與乘積展開
  • 广东省省考备考(第八十一天8.19)——资料分析、数量(强化训练)
  • MVC、MVP、MVCC 和 MVI 架构的介绍及区别对比
  • 面试题储备-MQ篇 2-说说你对RocketMQ的理解
  • 基于WebSocket和SpringBoot聊天项目ChatterBox测试报告
  • 怎样平衡NLP技术发展中数据质量和隐私保护的关系?