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++ 实现定时器的两种方法(线程定时和时间轮算法修改版)
定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。也可以利用c11的thread, mutex, condition_variable 来实现一个定时器。 1、使用C11中的thread, mutex, condition_variable来实现一个定时器。…...
2023mathorcup大数据竞赛选题建议及思路
大家好呀,昨天6点2023年第四届MathorCup高校数学建模挑战赛——大数据竞赛开赛,在这里给大家带来初步的选题建议及思路。 注意,本文章只是比较简略的图文讲解,更加详细完整的视频讲解请移步: 2023mathorcup大数据数学…...
部署vuepress项目到githubPage
部署vuepress项目到githubPage 1. 项目文件夹下有两个分支(main和gh-page) 1.1 main分支存放项目代码 1.2 gh-page分支存放 npm run docs:build之后的dist里面的所有文件 2. 分别提交到github上 3. 你的项目/docs/.vuepress/config.js module.export…...
ORACLE表空间说明及操作
ORACLE 表空间作用 数据存储:表空间是数据库中存储数据的逻辑结构。它提供了用于存储表、索引、视图、存储过程等数据库对象的空间。通过划分数据和索引等对象的存储,可以更好地管理和组织数据库的物理存储结构。性能管理和优化:通过将不同类…...
vue使用Element-plus的Image预览时样式崩乱
🔥博客主页: 破浪前进 🔖系列专栏: Vue、React、PHP ❤️感谢大家点赞👍收藏⭐评论✍️ 问题: 在使用组件库的image时出现了点小问题,预览的图片层级反而没有表格的层级高 效果图:…...
安装使用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语言的程序中,有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表,给出对应的识别码,然后跟据对应的表格来写出程序 2.程序设计 程序主要有循环判断构成。不需推理即可产生的符号我…...
Java项目中将MySQL改为8.0以上
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 maven依…...
软考高项-计算题(2)
题4 项目的总预算是包含管理储备的,所以总预算应该是:13238102*360 ETC(BAC-EV)/CPI BAC60 EV60*0.318 CPI18/200.9 ETC42/0.9 答案选择C A 题5 因为题目中提到了“按目前的状况继续发展”,那么是:ETC(BAC-EV)/CPI EV1230*0…...
Centos使用war文件部署jenkins
部署jenkins所需要的jdk环境如下: 这里下载官网最新的版本: 选择jenkins2.414.3版本,所以jdk环境最低得是java11 安装java11环境 这里直接安装open-jdk yum -y install java-11-openjdk.x86_64 java-11-openjdk-devel.x86_64下载jenkins最新…...
数据结构和算法——用C语言实现所有排序算法
文章目录 前言排序算法的基本概念内部排序插入排序直接插入排序折半插入排序希尔排序 交换排序冒泡排序快速排序 选择排序简单选择排序堆排序 归并排序基数排序 外部排序多路归并败者树置换——选择排序最佳归并树 前言 本文所有代码均在仓库中,这是一个完整的由纯…...
吃豆人C语言开发—Day2 需求分析 流程图 原型图
目录 需求分析 流程图 原型图 主菜单: 设置界面: 地图选择: 游戏界面: 收集完成提示: 游戏胜利界面: 游戏失败界面 死亡提示: 这个项目是我和朋友们一起开发的,在此声明一下…...
Nautilus Chain 联合香港数码港举办 BIG DEMO DAY活动,释放何信号?
在今年的 10 月 26 日 9:30-18:30 GMT8 期间,Nautilus Chain 联合香港数码港共同举办了 “BIG DEMO DAY” Web3 项目路演活动,包括Xwinner、Sleek、Tx、All weather、Coral Finance、DBOE、PARSIQ、Hookfi、Parallels、Fintestra 以及 dot.GAMING 等在内…...
手写RPC框架
文章目录 什么是RPC框架RPC框架中的关键点通信协议序列化协议动态代理和反射 目前已有的RPC框架手写RPC框架介绍项目框架项目执行流程项目启动 什么是RPC框架 RPC(Remote Procedure Call,远程过程调用), 简单来说遵循RPC协议的就是RPC框架. …...
音视频常见问题(六):视频黑边或放大
摘要 本文介绍了视频黑边或放大的原因和解决方案。主要原因包括视频分辨率与显示视图尺寸不一致、摄像头采集、美颜滤镜格式兼容和分辨率。为了解决这些问题,开发者可以选择合适的渲染模式、动态调整分辨率、处理视频旋转和使用自定义视频渲染。 即构音视频SDK提供…...
Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能
CameraX是JetPack库之一,通过CameraX可以向应用增加相机的功能。在下列内容中,将介绍一个结合CameraX实现一个简单的拍照应用。本应用必须采用Android SDK 34。并通过该简单示例,了解传统View层次组件的UI组件如何与Compose组件结合实现移动应…...
【每日一题Day361】LC2558从数量最多的堆取走礼物 | 大顶堆
从数量最多的堆取走礼物【LC2558】 给你一个整数数组 gifts ,表示各堆礼物的数量。每一秒,你需要执行以下操作: 选择礼物数量最多的那一堆。如果不止一堆都符合礼物数量最多,从中选择任一堆即可。选中的那一堆留下平方根数量的礼物…...
【psychopy】【脑与认知科学】认知过程中的面孔识别加工
目录 实验描述 实验思路 python实现 实验描述 现有的文献认为,人们对倒置的面孔、模糊的面孔等可能会出现加工时长增加、准确率下降的问题,现请你设计一个相关实验,判断不同的面孔是否会出现上述现象。请按照认知科学要求,画…...
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回退、还原】
上一篇:01【Git的基本命令、底层命令、命令原理】 下一篇:03【Git的协同开发、TortoiseGit、IDEA的操作Git】 文章目录 02【Git分支的使用、Git回退、还原】一、分支1.1 分支概述1.1.1 Git分支简介1.1.2 Git分支原理 1.2 创建分支1.2.1 创建普通分支1.…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
