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

这篇具有很好参考价值的文章主要介绍了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文章来源地址https://www.toymoban.com/news/detail-752794.html

到了这里,关于C++ 实现定时器的两种方法(线程定时和时间轮算法修改版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 多线程案例(3)-定时器

    大家好,我是晓星航。今天为大家带来的是 多线程案例三 相关的讲解!😀 定时器是什么 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就执行某个指定 好的代码. 定时器是一种实际开发中非常常用的组件. 比如网络通信中, 如果对方

    2024年02月14日
    浏览(28)
  • java多线程之定时器

    定时功能在java中主要是通过 Timer 类实现,因为它在内部还是使用多线程的方式进行处理,所以和多线程技术还是有非常大的管理 在JDK库中Timer类主要负责计划任务的功能,也就是在指定时间开始执行某一个任务,Timer类的主要功能就是设置计划任务,封装任务的类确是Timer

    2024年02月05日
    浏览(33)
  • 【javaEE】阻塞队列、定时器、线程池

    目录 🌴一、阻塞队列 1.概念 2.生产者消费者模型 3.阻塞队列的实现 🏹二、定时器 1.引出定时器 2.定时器的实现 🔥三、线程池 1.引出线程池 2.ThreadPoolExecutor 构造方法 3.标准数据库的4种拒绝策略【经典面试题】【重点掌握】 4.线程池的实现   1.概念 ✨对于队列,首先我们想

    2023年04月21日
    浏览(32)
  • Java多线程案例之定时器

    定时器是一种实际开发中非常常用的组件, 类似于一个 “闹钟”, 达到一个设定的时间之后, 就执行某个指定好的代码. 比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连. 比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自动删除). 类似于这样的场景就需要

    2024年02月20日
    浏览(38)
  • JavaEE & 线程案例 & 定时器 & 线程池 and 工厂模式

    欢迎光临 ^ V ^ 定时器,可以理解为闹钟 我们设立一个时间,时间一到,让一个线程跑起来~ 而Java标准库提供了一个定时器类: Timer ,from java.util 1.1 定时器Timer的使用 1.1.1 核心方法schedule 传入任务引用(TimerTask task)和 “定时”(long delay / ms) 由于TimerTask不是函数式接口,

    2023年04月18日
    浏览(30)
  • 多线程案例 | 单例模式、阻塞队列、定时器、线程池

    单例模式 单例模式是 设计模式 的一种 什么是设计模式? 设计模式好比象棋中的 “棋谱”,红方当头炮,黑方马来跳,针对红方的一些走法,黑方应招的时候有一些固定的套路,按照套路来走局势就不会吃亏,也就发明了一组\\\"棋谱\\\",称为设计模式 软件开发中也有很多常见

    2024年02月15日
    浏览(40)
  • 【JavaEE初阶】多线程(四)阻塞队列 定时器 线程池

    概念 阻塞队列是一种特殊的队列. 也遵守 “ 先进先出 ” 的原则. 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素. 当队列空的时候, 继续出队列也会阻塞,直到有其他线程往队列中插入元素

    2023年04月26日
    浏览(41)
  • 【Java】多线程案例(单例模式,阻塞队列,定时器,线程池)

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: 单例模式是设计模式之一。代码当中的某个类,只能有一个实例,不能有多个。单例模式分为:饿汉模式和懒汉模式 饿汉模式表示很着急,就想吃完饭剩下很多碗,然后一

    2024年02月06日
    浏览(35)
  • Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)

    设计模式就是软件开发中的“棋谱”,软件开发中也有很多常见的 “问题场景”。针对这些问题场景,大佬们总结出了一些固定的套路。按照这些套路来实现代码可能不会很好,但至少不会很差。当前阶段我们需要掌握两种设计模式: (1)单例模式 (2)工厂模式 概念/特征

    2024年02月09日
    浏览(42)
  • 【Java|多线程与高并发】定时器(Timer)详解

    在Java中,定时器 Timer 类是用于执行定时任务的工具类。它允许你安排一个任务在未来的某个时间点执行,或者以固定的时间间隔重复执行。 在服务器开发中,客户端向服务器发送请求,然后等待服务器响应. 但服务器什么时候返回响应,并不确定. 但也不能让客户端一直等下去

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包