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

C++ 实现定时器的两种方法(线程定时和时间轮算法修改版)

定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。也可以利用c++11的thread, mutex, condition_variable 来实现一个定时器。

1、使用C++11中的thread, mutex, condition_variable来实现一个定时器。
注:此算法会每一个任务创建一个线程,不推荐。推荐用最下面第2种时间轮算法

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>class Timer {
public:Timer() :_expired(true), _try_to_expire(false) {}Timer(const Timer& t) {_expired = t._expired.load();_try_to_expire = t._try_to_expire.load();}~Timer() {Expire();}void StartTimer(int interval, std::function<void()> task) {if (_expired == false) {return;}_expired = false;std::thread([this, interval, task]() {while (!_try_to_expire) {std::this_thread::sleep_for(std::chrono::milliseconds(interval));task();}{std::lock_guard<std::mutex> locker(_mutex);_expired = true;_expired_cond.notify_one();}}).detach();}void Expire() {if (_expired) {return;}if (_try_to_expire) {return;}_try_to_expire = true;{std::unique_lock<std::mutex> locker(_mutex);_expired_cond.wait(locker, [this] {return _expired == true; });if (_expired == true) {_try_to_expire = false;}}}private:std::atomic<bool> _expired;std::atomic<bool> _try_to_expire;std::mutex _mutex;std::condition_variable _expired_cond;
};int main() {Timer t;t.StartTimer(1000, []() {std::cout << "Hello World!" << std::endl; });std::this_thread::sleep_for(std::chrono::seconds(4));t.Expire();return 0;
}

2、使用时间轮算法:Linux内核就有这个算法。这里也有一个用户态的实现供参考:github.com/facebook/folly。它的高精度版本能实现微妙级别的定时。下面是一个简单的时间轮定时器的C++实现。原文的代码有问题,不能循环定时,经修改已经支持:


#include <chrono>
#include <functional>
#include <list>
#include <mutex>
#include <thread>
#include <vector>class TimerWheel {
public:using Task = std::function<void()>;explicit TimerWheel(size_t wheel_size, int interval_ms): wheel_size_(wheel_size),interval_ms_(interval_ms),wheel_(wheel_size),current_index_(0) {}~TimerWheel() {Stop();}void Start() {if (running_) {return;}running_ = true;thread_ = std::thread([this]() {while (running_) {std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms_));Tick();}std::cout << "timer oooops!" << std::endl;});thread_.detach();}void Stop() {if (!running_) {return;}running_ = false;if (thread_.joinable()) {thread_.join();}}void AddTask(int timeout_ms, Task task) {std::lock_guard<std::mutex> lock(mutex_);size_t ticks = timeout_ms / interval_ms_;size_t index = (current_index_ + ticks) % wheel_size_;size_t allindex = index;for (size_t i = 1 ; allindex < wheel_size_; i++){allindex = index * i;if (allindex >= wheel_size_)break;wheel_[allindex].push_back(task);}}private:void Tick() {std::lock_guard<std::mutex> lock(mutex_);auto& tasks = wheel_[current_index_];for (const auto& task : tasks) {task();}//tasks.clear();current_index_ = (current_index_ + 1) % wheel_size_;}private:size_t wheel_size_;int interval_ms_;std::vector<std::list<Task>> wheel_;size_t current_index_;bool running_ = false;std::thread thread_;std::mutex mutex_;
};

使用方法:
使用static声明以免被析构,可在cpp类外全局声明,第一个参数为任务容器最大数量,第二个参数为定时判断的毫秒数即最低检测时间单位

static TimerWheel timer(10, 1000);

在要使用的地方,启动并添加任务

timer.Start();
timer.AddTask(2000, []() {std::cout << "Task 1" << std::endl; });
timer.AddTask(3000, []() {std::cout << "Task 2" << std::endl; });

可以在需要的时候停止

timer.Stop();

原文链接:https://blog.csdn.net/sinat_28305511/article/details/131495316

相关文章:

C++ 实现定时器的两种方法(线程定时和时间轮算法修改版)

定时器要求在固定的时间异步执行一个操作&#xff0c;比如boost库中的boost::asio::deadline_timer&#xff0c;以及MFC中的定时器。也可以利用c11的thread, mutex, condition_variable 来实现一个定时器。 1、使用C11中的thread, mutex, condition_variable来实现一个定时器。…...

2023mathorcup大数据竞赛选题建议及思路

大家好呀&#xff0c;昨天6点2023年第四届MathorCup高校数学建模挑战赛——大数据竞赛开赛&#xff0c;在这里给大家带来初步的选题建议及思路。 注意&#xff0c;本文章只是比较简略的图文讲解&#xff0c;更加详细完整的视频讲解请移步&#xff1a; 2023mathorcup大数据数学…...

部署vuepress项目到githubPage

部署vuepress项目到githubPage 1. 项目文件夹下有两个分支&#xff08;main和gh-page&#xff09; 1.1 main分支存放项目代码 1.2 gh-page分支存放 npm run docs:build之后的dist里面的所有文件 2. 分别提交到github上 3. 你的项目/docs/.vuepress/config.js module.export…...

ORACLE表空间说明及操作

ORACLE 表空间作用 数据存储&#xff1a;表空间是数据库中存储数据的逻辑结构。它提供了用于存储表、索引、视图、存储过程等数据库对象的空间。通过划分数据和索引等对象的存储&#xff0c;可以更好地管理和组织数据库的物理存储结构。性能管理和优化&#xff1a;通过将不同类…...

vue使用Element-plus的Image预览时样式崩乱

&#x1f525;博客主页&#xff1a; 破浪前进 &#x1f516;系列专栏&#xff1a; Vue、React、PHP ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 问题&#xff1a; 在使用组件库的image时出现了点小问题&#xff0c;预览的图片层级反而没有表格的层级高 效果图&#xff1a;…...

安装使用vcpkg的简易教程

目录 1. 首先安装vcpkg2. 在vcpkg目录下运行bootstrap-vcpkg.bat 命令3. 接着vs进行集成4. 使用vcpkg搜索可用的包5.下载安装所需包6.下载安装完成 1. 首先安装vcpkg 使用git命令下载 git clone https://github.com/Microsoft/vcpkg.git如果下载失败可直接下载文件 (vcpkg-ma…...

制作一个简单的C语言词法分析程序

1.分析组成 C语言的程序中&#xff0c;有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表&#xff0c;给出对应的识别码&#xff0c;然后跟据对应的表格来写出程序 2.程序设计 程序主要有循环判断构成。不需推理即可产生的符号我…...

Java项目中将MySQL改为8.0以上

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 maven依…...

软考高项-计算题(2)

题4 项目的总预算是包含管理储备的&#xff0c;所以总预算应该是&#xff1a;13238102*360 ETC(BAC-EV)/CPI BAC60 EV60*0.318 CPI18/200.9 ETC42/0.9 答案选择C A 题5 因为题目中提到了“按目前的状况继续发展”&#xff0c;那么是&#xff1a;ETC(BAC-EV)/CPI EV1230*0…...

Centos使用war文件部署jenkins

部署jenkins所需要的jdk环境如下&#xff1a; 这里下载官网最新的版本&#xff1a; 选择jenkins2.414.3版本&#xff0c;所以jdk环境最低得是java11 安装java11环境 这里直接安装open-jdk yum -y install java-11-openjdk.x86_64 java-11-openjdk-devel.x86_64下载jenkins最新…...

数据结构和算法——用C语言实现所有排序算法

文章目录 前言排序算法的基本概念内部排序插入排序直接插入排序折半插入排序希尔排序 交换排序冒泡排序快速排序 选择排序简单选择排序堆排序 归并排序基数排序 外部排序多路归并败者树置换——选择排序最佳归并树 前言 本文所有代码均在仓库中&#xff0c;这是一个完整的由纯…...

吃豆人C语言开发—Day2 需求分析 流程图 原型图

目录 需求分析 流程图 原型图 主菜单&#xff1a; 设置界面&#xff1a; 地图选择&#xff1a; 游戏界面&#xff1a; 收集完成提示&#xff1a; 游戏胜利界面&#xff1a; 游戏失败界面 死亡提示&#xff1a; 这个项目是我和朋友们一起开发的&#xff0c;在此声明一下…...

Nautilus Chain 联合香港数码港举办 BIG DEMO DAY活动,释放何信号?

在今年的 10 月 26 日 9:30-18:30 GMT8 期间&#xff0c;Nautilus Chain 联合香港数码港共同举办了 “BIG DEMO DAY” Web3 项目路演活动&#xff0c;包括Xwinner、Sleek、Tx、All weather、Coral Finance、DBOE、PARSIQ、Hookfi、Parallels、Fintestra 以及 dot.GAMING 等在内…...

手写RPC框架

文章目录 什么是RPC框架RPC框架中的关键点通信协议序列化协议动态代理和反射 目前已有的RPC框架手写RPC框架介绍项目框架项目执行流程项目启动 什么是RPC框架 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;, 简单来说遵循RPC协议的就是RPC框架. …...

音视频常见问题(六):视频黑边或放大

摘要 本文介绍了视频黑边或放大的原因和解决方案。主要原因包括视频分辨率与显示视图尺寸不一致、摄像头采集、美颜滤镜格式兼容和分辨率。为了解决这些问题&#xff0c;开发者可以选择合适的渲染模式、动态调整分辨率、处理视频旋转和使用自定义视频渲染。 即构音视频SDK提供…...

Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能

CameraX是JetPack库之一&#xff0c;通过CameraX可以向应用增加相机的功能。在下列内容中&#xff0c;将介绍一个结合CameraX实现一个简单的拍照应用。本应用必须采用Android SDK 34。并通过该简单示例&#xff0c;了解传统View层次组件的UI组件如何与Compose组件结合实现移动应…...

【每日一题Day361】LC2558从数量最多的堆取走礼物 | 大顶堆

从数量最多的堆取走礼物【LC2558】 给你一个整数数组 gifts &#xff0c;表示各堆礼物的数量。每一秒&#xff0c;你需要执行以下操作&#xff1a; 选择礼物数量最多的那一堆。如果不止一堆都符合礼物数量最多&#xff0c;从中选择任一堆即可。选中的那一堆留下平方根数量的礼物…...

【psychopy】【脑与认知科学】认知过程中的面孔识别加工

目录 实验描述 实验思路 python实现 实验描述 现有的文献认为&#xff0c;人们对倒置的面孔、模糊的面孔等可能会出现加工时长增加、准确率下降的问题&#xff0c;现请你设计一个相关实验&#xff0c;判断不同的面孔是否会出现上述现象。请按照认知科学要求&#xff0c;画…...

File类的常用API

判断文件类型 public boolean isDirectory() public boolean isFile() 获取文件信息 public boolean exists() public String getAbsolutePath() public String getPath() 返回创建文件对象时传入的抽象路径的字符串形式 public String getName() public long lastModi…...

02【Git分支的使用、Git回退、还原】

上一篇&#xff1a;01【Git的基本命令、底层命令、命令原理】 下一篇&#xff1a;03【Git的协同开发、TortoiseGit、IDEA的操作Git】 文章目录 02【Git分支的使用、Git回退、还原】一、分支1.1 分支概述1.1.1 Git分支简介1.1.2 Git分支原理 1.2 创建分支1.2.1 创建普通分支1.…...

别再被网站当机器人了!手把手教你编译一个‘隐身版’Chromedriver(绕过Selenium检测)

从源码到隐身&#xff1a;深度定制Chromedriver绕过检测的工程实践 当你的Selenium脚本突然被目标网站拦截&#xff0c;熟悉的"Access Denied"页面赫然出现时&#xff0c;那种挫败感每个爬虫开发者都深有体会。网站的反爬系统越来越智能&#xff0c;常规的UserAgent轮…...

SEO_网站SEO优化完整教程:从入门到精通

SEO优化入门&#xff1a;从零基础到实战操作 随着互联网的迅猛发展&#xff0c;网站SEO优化成为了网站推广的重要手段。SEO&#xff0c;即搜索引擎优化&#xff0c;是通过优化网站的各项因素&#xff0c;使其在搜索引擎中获得更好的排名&#xff0c;从而吸引更多的流量。如何从…...

ResNet变体探索:从基础ResBlock到高效架构设计

1. ResBlock基础结构与设计哲学 残差块&#xff08;Residual Block&#xff09;作为ResNet的核心组件&#xff0c;彻底改变了深度神经网络的训练方式。我第一次在ImageNet分类任务中使用ResNet-50时&#xff0c;就被它解决梯度消失问题的能力震惊了——传统VGG网络在超过19层后…...

OpenClaw多模型对比:Qwen3-14b_int4_awq与开源小模型任务表现

OpenClaw多模型对比&#xff1a;Qwen3-14b_int4_awq与开源小模型任务表现 1. 测试背景与动机 最近在折腾OpenClaw自动化工作流时&#xff0c;发现一个关键问题&#xff1a;同样的任务脚本&#xff0c;换不同的大模型后端&#xff0c;执行效果差异巨大。为了找到最适合个人办公…...

网站推广seo优化公司如何做好移动端优化_网站推广seo优化公司如何提高网站的权重

网站推广seo优化公司如何做好移动端优化 在当前互联网市场的发展背景下&#xff0c;移动端的重要性日益凸显。无论是用户访问还是企业推广&#xff0c;移动端已经成为不可忽视的一部分。因此&#xff0c;网站推广seo优化公司在提升网站权重的过程中&#xff0c;移动端优化显得…...

代码写不动了?传统程序员不转型AI工程化提示词专家,将被AI助手彻底平替

2026年开年&#xff0c;全球科技圈的裁员潮撕开了行业变革的残酷真相&#xff1a;甲骨文一天内裁掉3万名员工&#xff0c;其中绝大多数是从事基础编码、数据库维护的传统程序员。取代他们的&#xff0c;正是曾经被视为“辅助工具”的AI助手。值得关注的是&#xff0c;在这场行业…...

嵌入式与单片机:核心概念与开发实战解析

1. 嵌入式与单片机&#xff1a;从概念到实战的全面解析作为一名在嵌入式领域摸爬滚打多年的工程师&#xff0c;我经常被问到这样一个问题&#xff1a;"单片机不就是嵌入式吗&#xff1f;"这个问题看似简单&#xff0c;却反映了初学者对这两个概念的普遍困惑。今天&am…...

2026届最火的五大降AI率方案推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 得从语言、逻辑以及细节这三方面着手&#xff0c;来降低AI生成内容所留下的痕迹。在语言方面…...

手把手教你用WouoUI-PageVersion打造128*64 OLED炫酷UI(附Air001移植避坑指南)

嵌入式UI开发实战&#xff1a;WouoUI-PageVersion在128*64 OLED屏上的高效移植与优化 在资源受限的嵌入式设备上实现流畅的UI动画一直是个技术挑战。本文将带你深入探索如何利用WouoUI-PageVersion框架&#xff0c;在仅有4KB RAM和32KB Flash的Air001等微控制器上&#xff0c;打…...

2025届学术党必备的六大降重复率神器横评

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当前&#xff0c;人工智能技术快速发展&#xff0c;这为毕业论文写作提供了新的辅助路径&…...