相应的参考链接与注释都在代码里面,不懂的可以直接点开链接查看。
注释:时间轮定时器是指定时间间隔和一轮的总时间进行定时,时间堆定时器是指定执行次数和时间间隔进行定时(不要删除定时器)。

时间轮定时器

TimeWheel.h

#pragma once#ifndef __TIMEWHEEL_H__
#define __TIMEWHEEL_H__
/*
参考链接
https://cloud.tencent.com/developer/article/1361827
https://www.cnblogs.com/zhongwencool/p/timing_wheel.html
*//************************************************************************/
/* TimeWheel实现了一个毫秒级别的定时器,最大支持到分钟级别
进行了修改了,定时器函数,支持接收任意参数,返回类型为void
/************************************************************************/
#include <functional>
#include <list>
#include <thread>
#include <mutex>typedef struct TimePos_
{//毫秒,秒,分钟int ms_pos;int s_pos;int min_pos;}TimePos;typedef struct EventInfo_
{//超时时间(为初始化的倍数)int interval;//回调函数std::function<void()>  call_back;//时间TimePos time_pos;//定时器IDint timer_id;}EventInfo;class TimeWheel
{public:TimeWheel();~TimeWheel();
public:/*step 以毫秒为单位,表示定时器最小时间粒度max_timer 表示定时器所能接受的分钟时间间隔,表示一轮时间的总分钟数*/int InitTimerWheel(int step,int max_min);//设置时间为TimeOut的事件时,根据TimeOut算出发生此事件时刻的指针位置{TriggerMin,TriggerS,TriggerMS};template<typename Func, typename... Args>int AddTimer(int interval, Func&& func, Args&& ... args);int DeleteTimer(int timer_id);private:int DoLoop();int GenerateTimerID();int InsertTimer(int diff_ms,EventInfo &einfo);int GetNextTrigerPos(int interval,TimePos &time_pos);int GetMS(TimePos time_pos);int DealTimeWheeling(std::list<EventInfo> leinfo);
private://此处不是链表,是链表数组的头指针,时间轮数组std::list<EventInfo> *_pCallbackList = nullptr;std::mutex            _mutex;//时间TimePos               _time_pos;//计数刻度int _lowCount = 0;int _midCount = 0;int _highCount = 0;//步长int _step_ms = 0;//定时器数量int _timer_count = 0;
};//增加计时器
/*
interval必须是_step_ms的倍数
*/
template<typename Func, typename... Args>
int TimeWheel::AddTimer(int interval, Func&& func, Args&& ... args)
{if (interval < _step_ms || interval % _step_ms != 0 || interval >= _step_ms * _lowCount * _midCount * _highCount){//std::cout << "time interval is invalid" << std::endl;return -1;}std::unique_lock<std::mutex> lock(_mutex);EventInfo einfo = { 0 };einfo.interval = interval;einfo.call_back = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);;//初始化事件的时间einfo.time_pos.ms_pos = _time_pos.ms_pos;einfo.time_pos.s_pos = _time_pos.s_pos;einfo.time_pos.min_pos = _time_pos.min_pos;//随机生成ideinfo.timer_id = GenerateTimerID();//插入定时器,定时器个数加一,返回定时器idInsertTimer(einfo.interval, einfo);_timer_count++;//std::cout << "insert timer success time_id: " << einfo.timer_id << std::endl;return einfo.timer_id;}
#endif  //__TIMEWHEEL_H__

TimeWheel.cpp

#include "TimeWheel.h"#include <iostream>
#include <windows.h>
#include <ctime>TimeWheel::TimeWheel()
{memset(&_time_pos, 0, sizeof(_time_pos));
}TimeWheel::~TimeWheel()
{}//初始化定时器
int TimeWheel::InitTimerWheel(int step_ms, int max_min)
{if (1000 % step_ms != 0){//std::cout << "step is not property, should be devided by 1000" << std::endl;return -1;}//毫秒,秒,分钟。int msNeedCount = 1000 / step_ms;int sNeedCount = 60;int minNeedCount = max_min;//事件//初始化链表的数组,数组里的元素为链表,时间轮数组_pCallbackList = new std::list<EventInfo>[msNeedCount + sNeedCount + minNeedCount];_step_ms = step_ms;//步长_lowCount = msNeedCount;_midCount = sNeedCount;_highCount = minNeedCount;std::thread th([&]{this->DoLoop();});th.detach(); return 0;
}
增加计时器
//int TimeWheel::AddTimer(int interval, std::function<void(void)>& call_back)
//{//  if (interval < _step_ms || interval % _step_ms !=0 || interval >= _step_ms * _lowCount * _midCount * _highCount)
//  {//      //std::cout << "time interval is invalid" << std::endl;
//      return -1;
//  }
//
//  std::unique_lock<std::mutex> lock(_mutex);
//
//  EventInfo einfo = {0};
//
//  einfo.interval = interval;
//  einfo.call_back = call_back;
//  //初始化事件的时间
//  einfo.time_pos.ms_pos = _time_pos.ms_pos;
//  einfo.time_pos.s_pos = _time_pos.s_pos;
//  einfo.time_pos.min_pos = _time_pos.min_pos;
//  //随机生成id
//  einfo.timer_id = GenerateTimerID();
//
//  //插入定时器,定时器个数加一,返回定时器id
//  InsertTimer(einfo.interval, einfo);
//  _timer_count++;
//
//  //std::cout << "insert timer success time_id: " << einfo.timer_id << std::endl;
//  return einfo.timer_id;
//
//}
//删除定时器
int TimeWheel::DeleteTimer(int timer_id)
{std::unique_lock<std::mutex> lock(_mutex);int i = 0;//最大事件个数int nCount = _lowCount + _midCount + _highCount;for (i = 0; i < nCount; i++){std::list<EventInfo>& leinfo = _pCallbackList[i];for (auto item = leinfo.begin(); item != leinfo.end(); item++){if (item->timer_id == timer_id){item = leinfo.erase(item);return 0;}}}if (i == nCount){//std::cout << "timer not found" << std::endl;return -1;}return 0;
}int TimeWheel::DoLoop()
{//std::cout << "........starting loop........" << std::endl;static int nCount = 0;while (true){std::this_thread::sleep_for(std::chrono::milliseconds(_step_ms));std::unique_lock<std::mutex> lock(_mutex);//std::cout << ".........this is " << ++nCount << "  loop........." << std::endl;TimePos pos = { 0 };TimePos last_pos = _time_pos;GetNextTrigerPos(_step_ms, pos);_time_pos = pos;if (pos.min_pos != last_pos.min_pos){std::list<EventInfo>& leinfo = _pCallbackList[_time_pos.min_pos + _midCount + _lowCount];DealTimeWheeling(leinfo);leinfo.clear();}else if (pos.s_pos != last_pos.s_pos){std::list<EventInfo>& leinfo = _pCallbackList[_time_pos.s_pos + _lowCount];DealTimeWheeling(leinfo);leinfo.clear();}else if (pos.ms_pos != last_pos.ms_pos){std::list<EventInfo>& leinfo = _pCallbackList[_time_pos.ms_pos];DealTimeWheeling(leinfo);leinfo.clear();}else{//std::cout << "error time not change" << std::endl;return -1;}lock.unlock();}return 0;
}//生成ID
int TimeWheel::GenerateTimerID()
{srand((int)time(0));int x = rand() % 0xffffffff;int cur_time = static_cast<int>(time(nullptr));return x | cur_time | _timer_count;
}//插入定时器
int TimeWheel::InsertTimer(int diff_ms, EventInfo &einfo)
{TimePos time_pos = { 0 };GetNextTrigerPos(diff_ms, time_pos);//数组的每一个元素都是一个list链表if (time_pos.min_pos != _time_pos.min_pos)_pCallbackList[_lowCount + _midCount + time_pos.min_pos].push_back(einfo);else if (time_pos.s_pos != _time_pos.s_pos)_pCallbackList[_lowCount + time_pos.s_pos].push_back(einfo);else if (time_pos.ms_pos != _time_pos.ms_pos)_pCallbackList[time_pos.ms_pos].push_back(einfo);return 0;
}//获得下一个结束位置的时间。
int TimeWheel::GetNextTrigerPos(int interval, TimePos &time_pos)
{int cur_ms = GetMS(_time_pos);int future_ms = cur_ms + interval;time_pos.min_pos = (future_ms / 1000 / 60) % _highCount;time_pos.s_pos = (future_ms % (1000 * 60)) / 1000;time_pos.ms_pos = (future_ms % 1000) / _step_ms;return 0;
}//获取当前毫秒数
int TimeWheel::GetMS(TimePos time_pos)
{return _step_ms * time_pos.ms_pos + time_pos.s_pos * 1000 + time_pos.min_pos * 60 * 1000;
}//处理事件
int TimeWheel::DealTimeWheeling(std::list<EventInfo> leinfo)
{for (auto item = leinfo.begin(); item != leinfo.end(); item++){int cur_ms = GetMS(_time_pos);int last_ms = GetMS(item->time_pos);int diff_ms = (cur_ms - last_ms + (_highCount + 1) * 60 * 1000) % ((_highCount + 1) * 60 * 1000);if (diff_ms == item->interval){item->call_back();item->time_pos = _time_pos;InsertTimer(item->interval, *item);}else{InsertTimer(item->interval - diff_ms, *item);}}return 0;}

测试
example.cpp

#include <iostream>
#include <functional>
#include <string>
#include "TimeWheel.h"
using namespace std;int g_count=0;void fun100(string s)
{g_count++;cout << s<<" "<<g_count << endl;
}
void fun200()
{cout << "func 200" << endl;
}
void fun500()
{cout << "func 500" << endl;
}void fun1500()
{cout << "func 1500" << endl;
}void main()
{/*std::function<void()> f100 = std::bind(&fun100);std::function<void()> f200 = std::bind(&fun200);std::function<void()> f500 = std::bind(&fun500);std::function<void()> f1500 = std::bind(&fun1500);*/TimeWheel time_wheel;time_wheel.InitTimerWheel(1000, 5);int timer1 = time_wheel.AddTimer(1000, fun100,"时间轮");//int timer2 = time_wheel.AddTimer(200, f200);//int timer3 = time_wheel.AddTimer(500, f500);// time_wheel.AddTimer(1500, f1500);bool b = true;int nLoop = 0;/*while (1){nLoop++;this_thread::sleep_for(chrono::milliseconds(300));if (b){time_wheel.AddTimer(1500, f1500);b = false;}if (nLoop == 3)time_wheel.DeleteTimer(timer1);}
*/system("pause");return;
}

时间堆定时器

锁文件 critical.h

#pragma once
#ifndef __CRITICAL_H__
#define __CRITICAL_H__#include <Windows.h>
namespace raii
{class critical {private:CRITICAL_SECTION* _crit;public:critical(CRITICAL_SECTION* crit);critical(const critical&) = delete;critical& operator =(const critical&) = delete;~critical();};inline critical::critical(CRITICAL_SECTION* crit) {_crit = crit;//进入临界区EnterCriticalSection(_crit);}inline critical::~critical() {//离开临界区LeaveCriticalSection(_crit);}
}#endif  //__CRITICAL_H__

time_heap.h

#pragma once
#ifndef __TIME_HEAP_H__
#define __TIME_HEAP_H__/*
参考链接
https://blog.csdn.net/qq_28398301/article/details/105015492
*/#include <future>
#include <functional>
//c++17
#include <type_traits>
#include "critical.h"class time_heap
{private:// 事件信息class event {friend class time_heap;private:intptr_t             _origin;    //源地址uint64_t               _ms;        //定时时长(按秒计算,可以是小数)uint32_t               _count;     //执行数std::function<void()>    _func;      //回调函数protected:public:event(intptr_t origin_, uint64_t ms_, uint32_t count_, std::function<void()>&& func_);event(const event&) = delete;event& operator =(const event&) = delete;~event() = default;// 删除函数void del();};// 返回数据template <class T>class result_data {friend class time_heap;private:event*                                     _info;      //事件信息std::shared_ptr<std::packaged_task<T()>>  _pack_func; //已包装的函数protected:public:bool                   valid;      //有效性uint32_t               count;      //执行数result_data(uint32_t count_, std::shared_ptr<std::packaged_task<T()>> pack_func_);result_data(const result_data&) = delete;result_data& operator =(const result_data&) = delete;~result_data() = default;// 获取执行结果T get();// 删除定时器void del();};// 堆节点struct node {uint64_t ms;                                //结束时间event*     info;node() = default;node(const node&) = delete;node(node&& that_);node& operator =(const node& that_);node& operator =(node&& that_);~node() = default;};std::atomic<bool>                 _death;         //结束CRITICAL_SECTION                    _cri;           //临界区node*                              _heap;          //最小堆uint32_t                           _max_size;      //最大存储数uint32_t                         _size;          //存储数uint64_t                           _event_time;    //插入时间HANDLE                                _event;         //事件static std::unique_ptr<time_heap> _instance;      //实例指针// 添加节点void add_node();// 删除节点void del_node(uint32_t index_);// 删除指定下标定时器void del_timer(uint32_t index_);// 重置定时器void reset_timer(uint32_t index_);// 扩容void expansion();
protected:
public:time_heap(uint32_t max_size_ = 64);~time_heap();// 单例static time_heap& instance();// 获取距当前时间(毫秒)uint64_t get_ms();// 添加template<typename Func, typename... Args>auto add(double second_, uint32_t count_, Func&& func_, Args&& ... args_);
};//事件构造函数
inline time_heap::event::event(intptr_t origin_, uint64_t ms_, uint32_t count_, std::function<void()>&& func_) :_origin(origin_),_ms(ms_),_count(count_),_func(std::move(func_))
{};//事件删除函数
inline void time_heap::event::del()
{auto timer = &time_heap::instance();raii::critical r1(&timer->_cri);//定时器ID/*强制类型转换参考https://blog.csdn.net/u014786409/article/details/93751093*/uint32_t index = static_cast<uint32_t>((_origin - reinterpret_cast<intptr_t>(&timer->_heap[1].ms)) / sizeof(node) + 1);timer->del_timer(index);
}//返回结果构造函数
template <class T>
inline time_heap::result_data<T>::result_data(uint32_t count_, std::shared_ptr<std::packaged_task<T()>> pack_func_) :_info(nullptr),_pack_func(pack_func_),//有效性为真valid(true),count(count_)
{}//返回结果:得到结果
template <class T>
inline T time_heap::result_data<T>::get()
{return _pack_func->get_future().get();
}//返回结果:删除函数
template <class T>
void time_heap::result_data<T>::del()
{if (valid) {//将有效性置为假,删除事件valid = false;_info->del();return;}
}/*
堆:复制构造函数
&&右值引用(临时变量)
参考
https://blog.csdn.net/kitekitebaby/article/details/72566145
*/
inline time_heap::node::node(node&& that_)
{memcpy_s(this, sizeof(node), &that_, sizeof(node));this->info->_origin = reinterpret_cast<intptr_t>(&this->info);//将that置为0memset(&that_, 0, sizeof(node));
}/*
堆:重载=
*/
inline time_heap::node& time_heap::node::operator =(const node& that_)
{if (&that_ == this) {return *this;}memcpy_s(this, sizeof(node), &that_, sizeof(node));this->info->_origin = reinterpret_cast<intptr_t>(&this->info);return *this;
}/*
堆:重载=
*/
inline time_heap::node& time_heap::node::operator =(node&& that_)
{if (&that_ == this) {return *this;}memcpy_s(this, sizeof(node), &that_, sizeof(node));this->info->_origin = reinterpret_cast<intptr_t>(&this->info);memset(&that_, 0, sizeof(node));return *this;
}/*
时间堆:删除定时器
*/
inline void time_heap::del_timer(uint32_t index_)
{raii::critical r1(&_cri);if (_size < index_) {return;}//从堆里面删除index的事件和节点delete _heap[index_].info;del_node(index_);
}/*
重置定时器;
将节点事件复制,定时时长更新。去掉老的,增加新的*/
inline void time_heap::reset_timer(uint32_t index_)
{raii::critical r1(&_cri);auto timer = std::move(_heap[index_]);//现在的时间+事件的定时时长,按秒计算timer.ms = get_ms() + timer.info->_ms * 1000; //结束时间del_node(index_);_heap[_size + 1] = std::move(timer);add_node();
}/*
获取时间
https://blog.csdn.net/qq_31175231/article/details/77923212
*/
inline uint64_t time_heap::get_ms()
{//返回当前时间距1970-1-1 的毫秒数return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}template<typename Func, typename... Args>
auto time_heap::add(double second_, uint32_t count_, Func&& func_, Args&&... args_)
{raii::critical r1(&_cri);auto current_size = _size + 1;if (current_size == _max_size) {expansion();}//c++11typedef typename std::result_of<Func(Args...)>::type  re_t;//c++17//using re_t = typename std::invoke_result<Func, Args...>::type; //回调函数返回类型//typedef typename std::invoke_result<Func, Args...>::type re_t;auto    task = std::make_shared<std::packaged_task<re_t()>>(std::bind(std::forward<Func>(func_), std::forward<Args>(args_)...));   //已包装回调函数指针std::shared_ptr<result_data<re_t>>   result = std::make_shared<result_data<re_t>>(count_, task);//返回数据uint64_t  mini_time = _heap[1].ms;//最小时间// 添加节点(添加事件,事件结束时间)_heap[current_size].ms = get_ms() + static_cast<int64_t>(second_) * 1000; //结束时间_heap[current_size].info = new event(reinterpret_cast<intptr_t>(&_heap[current_size].ms), static_cast<uint64_t>(second_), count_, [=]() {(*task)();if (--result->count == 0){result->valid = false;}else{task->reset();}});result->_info = _heap[current_size].info;add_node();// 决定是否唤醒if (mini_time != _heap[current_size].ms) {SetEvent(_event);_event_time = get_ms();}return result;
}
#endif  //__TIME_HEAP_H__

time_heap.cpp

#include "time_heap.h"
std::unique_ptr<time_heap> time_heap::_instance;time_heap::time_heap(uint32_t max_size_) :_death(false),_heap(new node[max_size_]{}),_max_size(max_size_),_size(0),_event(CreateEvent(NULL, FALSE, FALSE, NULL))
{// 初始化临界区InitializeCriticalSection(&_cri);std::thread work_thread([&] {DWORD wait_re, ms = INFINITE;std::shared_ptr<std::function<void()>> func;while (true) {wait_re = ms ? WaitForSingleObject(_event, ms) : WAIT_TIMEOUT;if (!_size) {ms = INFINITE;continue;}if (_death) {break;}auto current_ms = get_ms();raii::critical r1(&_cri);if (wait_re == WAIT_OBJECT_0) {     //事件ms = static_cast<DWORD>(current_ms > _heap[1].ms ? 0 : (_heap[1].ms - current_ms - (current_ms - _event_time)));}else if (wait_re == WAIT_TIMEOUT) {    //超时//printf("超时\n");_heap[1].info->_func();if (_heap[1].info->_count == INFINITE) {reset_timer(1);}else if (--_heap[1].info->_count == 0){del_timer(1);}else {reset_timer(1);}ms = static_cast<DWORD>(_size > 0 ? _heap[1].ms - current_ms : INFINITE);}else if (wait_re == WAIT_FAILED) {  //失败printf("失败: %I64d\n", current_ms);}}});work_thread.detach();
}time_heap::~time_heap()
{_death = true;{raii::critical r1(&_cri);// 退出工作线程SetEvent(_event);for (; _size > 0; --_size) {delete _heap[_size].info;}delete[] _heap;}DeleteCriticalSection(&_cri);
}void time_heap::add_node()
{raii::critical r1(&_cri);uint32_t index1 = ++_size, index2 = index1 >> 1;while (index1 > 1 && _heap[index2].ms > _heap[index1].ms) {std::swap(_heap[index1], _heap[index2]);index1 = index2;index2 >>= 1;}
}/*
堆排序
参考链接
https://blog.csdn.net/wangrenhaioylj/article/details/108565134*/void time_heap::del_node(uint32_t index_)
{raii::critical r1(&_cri);if (_size < index_) {return;}// 向下调整if (_heap[_size].ms > _heap[index_].ms) {uint32_t index1 = index_, index2 = index1 << 1;while (index2 < _size) {if (_heap[index2].ms > _heap[index2 + 1].ms) {++index2;}if (_heap[_size].ms > _heap[index2].ms) {_heap[index1] = _heap[index2];index1 = index2;index2 <<= 1;}else {break;}}_heap[index1] = _heap[_size];memset(&_heap[_size], 0, sizeof(node));}// 向上调整else if (_heap[_size].ms < _heap[index_].ms) {uint32_t index1 = index_ >> 1, index2 = _size;while (_heap[index1].ms > _heap[index2].ms) {std::swap(_heap[index1], _heap[_size]);index2 = index1;index1 >>= 1;}_heap[index_] = _heap[_size];memset(&_heap[_size], 0, sizeof(node));}// 不做调整else {_heap[index_] = _heap[_size];memset(&_heap[_size], 0, sizeof(node));}if (--_size > 0) {_event_time = get_ms();SetEvent(_event);}
}void time_heap::expansion()
{auto size = sizeof(node) * _max_size;node* new_heap = new node[_max_size <<= 1]{};raii::critical r1(&_cri);memcpy_s(new_heap, size << 1, _heap, size);delete[] _heap;_heap = new_heap;
}/*
参考
https://blog.csdn.net/ynshi57/article/details/108083019
https://www.cnblogs.com/xuhuajie/p/11647164.html*/
time_heap& time_heap::instance()
{static std::once_flag s_flag;std::call_once(s_flag, [&]() {_instance.reset(new time_heap);});return *_instance;
}

使用example.cpp

#include "time_heap.h"/*
使用说明:在删除定时器之前(务必不要删除,否则只执行一次)初始化
auto &timer = time_heap::instance();
加入定时器,参数:秒(可以填小数,转换为毫秒),指定执行次数,函数,函数的参数。
auto timer1 = timer.add(second, count,test_1, g_index);//得到返回结果,返回为void的 不需要执行,否则出错
if (timer1->valid) {
auto result = timer1->get();
}删除
timer1->del();
*/int g_index = 0;int test_1(int index)
{g_index++;printf("%d\n", g_index);return 0;
}void main()
{auto &timer = time_heap::instance();//定时时长(单位:秒,由于是double可以传入0.05这样的数字,会自动转为毫秒)double second = 0.001;//执行次数uint32_t count = 1001;  //timer.add函数的返回值是一个std::shared_ptr对象。不用手动销毁//auto timer1 = timer.add(second, count, [&](int index) {//    printf("%d\n",index);//   return index;//}//, 7); //不定参,可以使用任意类型个数的参数auto timer1 = timer.add(second, count,test_1, g_index);//获取事件函数返回值(若未事件未执行完成将堵塞)//auto result = timer1->get();//安全的获取事件函数返回值(若未事件未执行完成将堵塞,超过count次get完成后再次get将cash)/*返回是void的话,不需要执行。*/if (timer1->valid) {auto result = timer1->get();}//printf("%d\n", result);//timer1->del();              //删除定时事件//system("pause");getchar();return;
}

c++ 时间轮与时间堆定时器相关推荐

  1. Linux网络编程 | 高性能定时器 :时间轮、时间堆

    文章目录 时间轮 时间堆 在上一篇博客中我实现了一个基于排序链表的定时器容器,但是其存在一个缺点--随着定时器越来越多,添加定时器的效率也会越来越低. 而下面的两个高效定时器--时间轮.时间堆,会完美 ...

  2. 时间轮和时间堆管理定时器

    高性能定时器 时间轮 由于排序链表定时器容器有这样一个问题:添加定时器的效率偏低.而即将介绍的时间轮则解决了这个问题.一种简单的时间轮如下所示. 如图所示的时间轮内,指针指向轮子上的一个slot(槽) ...

  3. Linux服务器开发,定时器方案红黑树,时间轮,最小堆

    ─────────────────────────────────────────────────────────────── ┌------------┐ │▉▉♥♥♥♥♥♥♥♥ 99% │ ♥❤ ...

  4. 技术精讲丨多线程环境下时间轮-海量定时任务的定时器设计

    多线程环境下海量定时任务处理-定时器设计 1.  定时器设计 2.  红黑树.最小堆以及跳表的实现对比 3.  时间轮的实现 视频讲解如下,点击观看: 技术精讲丨多线程环境下时间轮-海量定时任务的定时 ...

  5. kafka时间轮linux时间轮,Kafka解惑之时间轮 (TimingWheel)

    Kafka中存在大量的延迟操作,比如延迟生产.延迟拉取以及延迟删除等.Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定 ...

  6. 后端开发【一大波有用知识】定时器方案红黑树,时间轮,最小堆

    目录: 一.如何组织定时任务? 定时器收网络IO处理造成误差特别大,该怎么处理? 用何种数据机构存储定时器? 红黑树如何解决相同时间的key值的? 最小堆 时间轮 一个帮助理解单层级时间轮的例子 如何 ...

  7. 高性能计时器Timer的设计(时间轮和时间堆两种方式)

    时间轮 前文提到,基于排序链表的定时器存在一个问题:添加定时器的效率偏低.一种简单的时间轮如图所示: 在这个时间轮中,实线指针指向轮子上的一个槽(slot).它以恒定的速度顺时针转动,每转动一步就指向 ...

  8. 杂乱无序的时间轮:有效实现定时器功能的数据结构

    <实现较低的计时器粒度以重传TCP(RTO):时间轮算法如何减少开销> <分级时间轮优化普通时间轮定时器> <分级时间轮优化普通时间轮定时器(2):滴答式分层计时轮> ...

  9. 高性能定时器--时间轮/多级时间轮

    运行原理 指针指向轮子上的一个槽,轮子以恒定的速度顺时针转动,每转动一步就指向下一个槽(虚线指针指向的槽),每次转动称为一个tick,一个tick的时间称为时间轮的槽间隔slot interval,即 ...

  10. linux现代时间轮算法,linux2.6定时器的时间轮算法分析

    1.Overview 常用的定时器实现算法有两种:红黑树和时间轮(timing wheel). 在Linux2.6的代码中,kernel/timer.c文件实现了一个通用定时器机制,使用的是时间轮算法 ...

最新文章

  1. ERP系统管理员的工具箱 推荐几款优秀的数据比较同步工具 Data Compare and Sync tool...
  2. java 连接数据库之一个完整的函数
  3. Mac OS Yosemite 文件批量重命名
  4. Android Navigation Drawer(导航抽屉)
  5. https nginx phpstudy_让phpStudy2018 Nginx 支持WordPress自定义链接
  6. CentOS 7安装Nginx
  7. TensorFlow 实战 MINST
  8. CPU/ABI显示No system images installed for this target的解决方案
  9. keycloak mysql_keycloak搭配mysql
  10. Hexo博客NexT主题美化之新增看板娘(能说话、能换装)
  11. python中布尔运算可以用于浮点数比较_简单谈谈Python中的几种常见的数据类型
  12. Python 字典(Dictionary) items()方法
  13. 2021-09-03din 与dien
  14. Mac上运行matlab2019b卡顿
  15. H3C 无线控制器WX2510H-F与无线接入点WA5320-C-EI的安装与关联详细指导书
  16. 华为USG6000单臂路由
  17. 如何通过手机设置苹果账户的双重认证
  18. 误差反向传播法实现手写数字识别(纯numpy实现)
  19. java-php-python-ssm“花花世界”网站计算机毕业设计
  20. ELF文件格式, ELF文件是什么,里面包含什么内容

热门文章

  1. 错题集--大一C语言选择题
  2. Excel筛选后填充
  3. VDN平台各种数据库连接设置
  4. WPF 加载GIF图片
  5. wordpress自动采集插件wp-autopost-pro 3.7.8 完美绿色版
  6. 综合布线实训室解决方案(转载)
  7. 微信小程序跳转外部链接
  8. 想自学HCIE,有什么好的书籍推荐吗?
  9. micropython 移植k210_重构+优化 micropython 下 k210 (esp8285) 的 AT network 通信过程(附代码,顺便讲讲状态机实现)。...
  10. 系统分析与设计期末复习题目