C++ 定时器实现和时间轮介绍
定时器是计算机系统中非常常见的一种机制,可以用来在一定时间间隔后执行某些操作,或在特定时间点执行某些操作。在 C++ 编程中,我们可以使用定时器来进行任务调度等操作。其中,时间轮是一种常见的定时器实现方式,下面将详细介绍时间轮的概念和实现,以及如何在 C++ 中进行定时器的编写。
什么是时间轮?
时间轮是一种基本的定时器实现方法,它将时间线划分成多个区间,每个区间代表一个时间间隔,每个槽位代表了一个定时任务。时间轮中还有一个指针,指向当前正在执行的槽位,每经过一个时间间隔,指针会向后移动一个槽位。当指针指向某个槽位时,就会执行该槽位中的定时任务。
时间轮的优点在于,可以快速定位到需要执行的定时任务,并且可以处理高并发的情况,即可以同时管理多个定时任务。
时间轮的实现方法
时间轮的实现方法相对简单,可以使用一个循环数组来存储各个槽位,使用一个指针来指向当前执行的槽位,每经过一个时间间隔,指针就会向后移动一个槽位。当执行到某个槽位时,就会执行该槽位中的所有定时任务。
具体实现可以分为以下步骤:
- 创建时间轮对象,存储循环数组和指针
- 向时间轮中添加定时任务,计算定时任务在时间轮中对应的槽位,将定时任务插入槽位
- 启动时间轮,开始执行定时任务
- 每经过一个时间间隔,指针向后移动一个槽位,并执行该槽位中的所有定时任务
- 当时间轮执行完一圈时,重新回到第一个槽位,继续执行定时任务,直到时间轮被停止
以下是使用 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技术站