C++定时器实现和时间轮介绍

C++ 定时器实现和时间轮介绍

定时器是计算机系统中非常常见的一种机制,可以用来在一定时间间隔后执行某些操作,或在特定时间点执行某些操作。在 C++ 编程中,我们可以使用定时器来进行任务调度等操作。其中,时间轮是一种常见的定时器实现方式,下面将详细介绍时间轮的概念和实现,以及如何在 C++ 中进行定时器的编写。

什么是时间轮?

时间轮是一种基本的定时器实现方法,它将时间线划分成多个区间,每个区间代表一个时间间隔,每个槽位代表了一个定时任务。时间轮中还有一个指针,指向当前正在执行的槽位,每经过一个时间间隔,指针会向后移动一个槽位。当指针指向某个槽位时,就会执行该槽位中的定时任务。

时间轮的优点在于,可以快速定位到需要执行的定时任务,并且可以处理高并发的情况,即可以同时管理多个定时任务。

时间轮的实现方法

时间轮的实现方法相对简单,可以使用一个循环数组来存储各个槽位,使用一个指针来指向当前执行的槽位,每经过一个时间间隔,指针就会向后移动一个槽位。当执行到某个槽位时,就会执行该槽位中的所有定时任务。

具体实现可以分为以下步骤:

  1. 创建时间轮对象,存储循环数组和指针
  2. 向时间轮中添加定时任务,计算定时任务在时间轮中对应的槽位,将定时任务插入槽位
  3. 启动时间轮,开始执行定时任务
  4. 每经过一个时间间隔,指针向后移动一个槽位,并执行该槽位中的所有定时任务
  5. 当时间轮执行完一圈时,重新回到第一个槽位,继续执行定时任务,直到时间轮被停止

以下是使用 C++ 实现时间轮的代码示例:

#include <iostream>
#include <vector>
#include <functional>
#include <chrono>
#include <thread>

using namespace std::chrono_literals;

class Timer {
public:
    Timer(size_t wheelSize, size_t tickDuration)
        : m_wheelSize(wheelSize), m_tickDuration(tickDuration), m_currentTick(0), m_wheel(wheelSize), m_stop(false)
    {
        m_wheel[0].resize(0xffffffffu / wheelSize + 1);  // 根据 wheelSize 计算每个槽位能包含的最大超时时间
    }

    void start()
    {
        m_stop = false;
        m_ticksThread = std::thread([this] {
            while (!m_stop) {
                std::this_thread::sleep_for(m_tickDuration);
                onTick();
            }
        });
    }

    void stop()
    {
        m_stop = true;
        if (m_ticksThread.joinable()) {
            m_ticksThread.join();
        }
    }

    template <typename FuncType>
    void addTimer(size_t timeoutMs, FuncType&& func)
    {
        if (m_stop) {
            return;
        }
        auto wheelIdx = (m_currentTick + (timeoutMs / m_tickDuration)) % m_wheelSize;  // 获取任务应该插入的槽位
        auto& bucket = m_wheel[wheelIdx];
        bucket.emplace_back(std::forward<FuncType>(func));
    }

private:
    void onTick()
    {
        auto& bucket = m_wheel[m_currentTick % m_wheelSize];            
        for (auto& func : bucket) {  // 执行当前槽位中的任务
            func();
        }
        bucket.clear();
        m_currentTick = (m_currentTick + 1) % m_wheelSize;  // 将时间轮指针向后移动一个槽位
    }

private:
    size_t m_wheelSize;
    size_t m_tickDuration;
    size_t m_currentTick;
    std::vector<std::vector<std::function<void()>>> m_wheel;
    std::thread m_ticksThread;
    bool m_stop;
};

int main()
{
    Timer timer(60, 100ms);  // 创建时间轮,60 个槽位,每个槽位 100 ms
    timer.start();  // 启动时间轮

    for (int i = 0; i < 1000; i++) {  // 添加 1000 个定时任务
        timer.addTimer(i * 10, [i] {
            std::cout << "Task " << i << " is executed at " << std::chrono::system_clock::now().time_since_epoch().count() << std::endl;
        });
    }

    std::this_thread::sleep_for(15s);  // 等待 15s,让时间轮执行完毕

    timer.stop();  // 停止时间轮

    return 0;
}

使用 boost 实现定时器

除了手动实现时间轮,我们还可以使用 boost 库提供的定时器组件来实现定时器。下面是使用 boost 定时器组件实现定时器的代码示例:

#include <iostream>
#include <boost/asio.hpp>

using namespace boost::asio;

int main()
{
    io_service io;
    deadline_timer t(io, boost::posix_time::seconds(5));  // 创建一个定时器,5s 后触发

    t.wait();  // 等待定时器触发

    std::cout << "Timer is expired." << std::endl;

    return 0;
}

上面的代码创建了一个定时器,5s 后触发,使用 wait 函数等待定时器触发。需要注意的是,使用 boost 定时器组件时需要注意线程安全性问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++定时器实现和时间轮介绍 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • c++11封装thread库的方法示例

    C++11封装thread库的方法示例 本文讲解在C++11中如何使用thread库进行线程管理,通过封装实现线程安全的应用程序。 为什么要使用线程 在计算机科学中,线程表示程序中执行的一条路径。一个进程通常包含一个或多个线程,多个线程可以并行执行,提高程序的处理效率;同时,也方便了对于程序中复杂、耗时的操作的调度和管理。 介绍封装thread库的方法 C+…

    C 2023年5月22日
    00
  • Django Rest framework之认证的实现代码

    下面我为您详细讲解Django Rest Framework(DRF)中实现认证的代码攻略。 1、DRF认证方式 DRF提供了多种认证方式,包括: BasicAuthentication:HTTP的基本认证方式,不安全,适用于内部系统或测试环境; TokenAuthentication:使用token实现的认证方式,适用于前后端分离项目; SessionAu…

    C 2023年5月23日
    00
  • C 表达式中的汇编指令

    C语言表达式中的汇编指令,通常可以通过内嵌汇编或者 inline assembly 的方式实现。所谓内嵌汇编,就是将汇编指令嵌入到C语言程序中,与C语句混在一起。这种方式可以很好的利用汇编指令来进行高级优化并完成一些特殊功能。下面就让我们来分别介绍内嵌汇编与 inline assembly 的实现方式以及示例讲解。 内嵌汇编 内嵌汇编可以分为两种方式,一种是…

    C 2023年5月23日
    00
  • C语言中的正则表达式使用示例详解

    C语言中的正则表达式使用示例详解 正则表达式是一种通用的文本匹配模式,可以在C语言中用来进行字符串的匹配和处理。C语言提供了regex库来支持正则表达式的使用。接下来,将为您详细讲解C语言中正则表达式的使用,包括正则表达式语法、函数调用和示例说明。 正则表达式语法 正则表达式语法是一组规则,用于描述文本模式匹配的方式。在C语言中,正则表达式的语法由一些特殊字…

    C 2023年5月23日
    00
  • C语言代码实现猜数字游戏

    下面是C语言代码实现猜数字游戏的完整攻略。 1. 题目要求 猜数字游戏是一款非常简单的游戏,游戏的规则如下: 程序会随机生成一个数字,数字的范围为1-100; 玩家可以输入一个数字,程序会告诉玩家这个数字是正确的、偏大还是偏小; 如果玩家猜对了数字,游戏结束,否则会提示玩家再次输入数字继续猜。 我们要在C语言中实现这个游戏。 2. 代码实现 代码实现分为以下…

    C 2023年5月22日
    00
  • C语言编程入门必背的示例代码整理大全

    您好,关于“C语言编程入门必背的示例代码整理大全”的完整攻略,以下是详细讲解: 概述 此文档旨在为初学者提供C语言编程入门示例代码整理大全,内容包括语法基础、数组指针、结构体等知识点。示例代码将以最简单易懂的方式呈现,并加入详细注释,以帮助初学者更好地理解和学习。 语法基础 Hello World #include <stdio.h> int m…

    C 2023年5月23日
    00
  • PHP的JSON封装、转变及输出操作示例

    针对PHP的JSON封装、转变及输出操作,下面给出完整的攻略。 1. JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。它是由Douglas Crockford发明的,目前已成为互联网数据交换中十分流行的标准格式之一。JSON格式有两种数据结构,分别是对象和数组。 2. PHP中JSON…

    C 2023年5月23日
    00
  • C++内存四区之代码区、全局区、栈区和堆区

    C++内存四区指的是程序在运行时所使用的内存分为代码区、全局区、栈区和堆区。下面我们分别来讲解一下这四个区域。 1. 代码区 代码区是存储函数体等二进制代码的区域,它需要保护,以免被其他程序或者用户修改。代码区一般位于内存的高地址部分,从而防止由于栈溢出操作而覆盖代码区。 代码示例: #include <iostream> int main() …

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部