时间轮定时器

优点:可保证每次执行定时器任务都是O(1)复杂度,在定时器任务密集的情况下,性能优势非常明显。

缺点:内存占用较大,当定时器使用不频繁,处理时间跨度很大的时候,效率低下。

C++实现:

// timer.h

#pragma once

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

template

class Timer {

public:

using NormalTime = std::tuple<:uint8_t std::uint8_t std::uint16_t>;

static NormalTime TimeNormal(std::uint64_t time)

{

auto d = (std::uint8_t)(time / 86400000); time -= d * 86400000;

auto h = (std::uint8_t)(time / 3600000); time -= h * 3600000;

auto m = (std::uint8_t)(time / 60000); time -= m * 60000;

auto s = (std::uint8_t)(time / 1000); time -= s * 1000;

auto ms = (std::uint16_t)time;

return { d, h, m, s, ms };

}

static std::uint64_t TimeNormalNeg(const NormalTime & normal)

{

return std::get<0>(normal) * 86400000

+ std::get<1>(normal) * 3600000

+ std::get<2>(normal) * 60000

+ std::get<3>(normal) * 1000

+ std::get<4>(normal);

}

private:

struct Task {

Task()

{ }

Task(const std::size_t _id,

const std::uint64_t & _time,

const std::function & _func) : id(_id), time(_time), func(_func), normal(TimeNormal(_time))

{ }

bool operator==(const Task & other) const

{

return other.id == id;

}

bool operator==(std::size_t id) const

{

return this->id == id;

}

std::function func;

std::uint64_t time;

NormalTime normal;

std::size_t id;

};

struct Slot {

std::array<:vector>, Day> day;

std::array<:vector>, 24> hour;

std::array<:vector>, 60> minute;

std::array<:vector>, 60> second;

std::array<:vector>, 1000> millis;

};

public:

Timer(std::uint64_t time)

: _slot(new Slot())

, _startTime(time)

, _lastTime(0)

{ }

~Timer()

{ }

void Set(std::size_t id, std::uint64_t time, const std::function & func)

{

InsertTo<0>(Task(id, time - _startTime, func));

}

void Timer::Del(size_t id)

{

RemoveFrom(_slot->day.begin(), _slot->day.end(), id)

|| RemoveFrom(_slot->hour.begin(), _slot->hour.end(), id)

|| RemoveFrom(_slot->minute.begin(), _slot->minute.end(), id)

|| RemoveFrom(_slot->second.begin(), _slot->second.end(), id)

|| RemoveFrom(_slot->millis.begin(), _slot->millis.end(), id);

}

void Update(std::uint64_t time)

{

if (time > _lastTime + _startTime)

{

do {

auto[fromd1, fromh1, fromm1, froms1, fromms1] = TimeNormal(_lastTime);

_lastTime += std::min(time - _startTime - _lastTime, 16ULL);

auto[fromd2, fromh2, fromm2, froms2, fromms2] = TimeNormal(_lastTime);

Update<0, Day>(_slot->day.begin(), fromd1, fromd2);

Update<1, 24>(_slot->hour.begin(), fromh1, fromh2);

Update<2, 60>(_slot->minute.begin(), fromm1, fromm2);

Update<3, 60>(_slot->second.begin(), froms1, froms2);

Update<4, 1000>(_slot->millis.begin(), fromms1, fromms2);

} while (_lastTime + _startTime != time);

}

}

private:

template

bool RemoveFrom(Iter first, Iter last, size_t id)

{

for (; first != last; ++first)

{

auto iter = std::find_if(first->begin(), first->end(),

[id](const Task & task) { return task == id; });

if (iter != first->end())

{

first->erase(iter);

return true;

}

}

return false;

}

template

void Update(Iter iter, std::uint64_t first, std::uint64_t last)

{

if (first != last)

{

for (first = (first + 1) % N; first != last; first = (first + 1) % N)

{

Update(*std::next(iter, (std::ptrdiff_t)first));

}

Update(*std::next(iter, (std::ptrdiff_t)first));

}

}

template

void Update(std::vector & tasks)

{

std::for_each(tasks.begin(), tasks.end(),

std::bind(&Timer::InsertTo, this, std::placeholders::_1));

tasks.clear();

}

template

void InsertTo(const Task & task)

{

if constexpr (N == 5)

{

std::invoke(task.func);

}

else if (std::get(task.normal) == 0)

{

InsertTo(task);

}

else if (std::get(task.normal) != 0)

{

if constexpr (N == 0)

{

_slot->day.at(std::get<0>(task.normal)).emplace_back(task);

}

else if constexpr (N == 1)

{

_slot->hour.at(std::get<1>(task.normal)).emplace_back(task);

}

else if constexpr (N == 2)

{

_slot->minute.at(std::get<2>(task.normal)).emplace_back(task);

}

else if constexpr (N == 3)

{

_slot->second.at(std::get<3>(task.normal)).emplace_back(task);

}

else if constexpr (N == 4)

{

_slot->millis.at(std::get<4>(task.normal)).emplace_back(task);

}

}

}

private:

uint64_t _lastTime;

uint64_t _startTime;

std::unique_ptr _slot;

};

// main.cpp

#include "timer/timer.h"

#include

#include

std::int64_t NowTime(std::int64_t time)

{

return std::chrono::time_point_cast<:chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count() + time;

}

int main()

{

auto now = NowTime(0);

Timer<31> timer(now);

timer.Set(0, NowTime(5000), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(100), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(0), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(33), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(2333), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(2007), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(3600), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(60000), [now]() { std::cout << NowTime(0) - now << std::endl; });

timer.Set(0, NowTime(61050), [now]() { std::cout << NowTime(0) - now << std::endl; });

while (true)

{

now = NowTime(0);

timer.Update(now);

}

return 0;

}

linux内核使用的是时间轮定时器,因为内核必须考虑定时器任务密集的情况,同时,内核很容易保证时间跨度是固定的。其他场合下,用堆来实现定时器比较合适。

时间轮python_算法 数据结构——时间轮定时器相关推荐

  1. 时间排序python_算法导论 第八章 线性时间排序(python)

    比较排序:各元素的次序依赖于它们之间的比较{插入排序O(n**2) 归并排序O(nlgn) 堆排序O(nlgn)快速排序O(n**2)平均O(nlgn)} 本章主要介绍几个线性时间排序:(运算排序非比 ...

  2. 负载均衡轮询算法和服务器性能,负载均衡算法

    对于要实现高性能集群,选择好负载均衡器很重要,同时针对不同的业务场景选择合适的负载均衡算法也是非常重要的. 一.负载均衡算法分类 任务平分类 负载均衡系统将收到的任务平均分配给服务器进行处理,这里的& ...

  3. 【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(下)

    承接上文 承接上一篇文章[算法数据结构专题]「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)]我们基本上对层级时间轮算法的基本原理有了一定的认识, ...

  4. 时间轮timewheel算法

    时间轮是个不太常见,但在部分场景有较高使用价值的工具. 时间轮常用于延时任务,在Netty.akka.Quartz.Zookeeper等高性能组件中都存在时间轮定时器的踪影. 从定时任务说起 自然界中 ...

  5. java 时间轮算法_时间轮算法(TimingWheel)是如何实现的?

    前言 我在2. SOFAJRaft源码分析-JRaft的定时任务调度器是怎么做的?这篇文章里已经讲解过时间轮算法在JRaft中是怎么应用的,但是我感觉我并没有讲解清楚这个东西,导致看了这篇文章依然和没 ...

  6. 时间轮python_源码笔记:Nodejs 如何高效的获取时间戳而不影响性能的?

    本书的好看版本: 本书好看版本:215566435/Fz-node,喜欢的 ,多谢 前言 在昨天方正:玩了将近两年nodejs后,最近发现已经碰到天花板了.希望各位前辈能指点迷津?,的回答中,我提出了 ...

  7. 小顶堆时间复杂度_时间轮算法以及时间轮在Netty和Kafka中的应用的

    大家好,我是yes. 最近看 Kafka 看到了时间轮算法,记得以前看 Netty 也看到过这玩意,没太过关注.今天就来看看时间轮到底是什么东西. 为什么要用时间轮算法来实现延迟操作? 延时操作 Ja ...

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

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

  9. 数据结构与算法的时间空间复杂度

    提到数据结构与算法就不得不提时间复杂度和空间复杂度,本人看大部分文章介绍都比较晦涩难懂,就想着用简单的代码示例快速让你理解数据结构与算法的时间空间复杂度. 首先,时间复杂度表示的是使用某个数据结构或者 ...

最新文章

  1. 如何选择分布式系统(区块链)协议?
  2. 使用dumpsys检测Activity任务栈
  3. Jenkins配置基于角色的项目权限管理--转
  4. 堆(heap)和栈(stack)的区别
  5. 解决BDOC structure里header和data structure里数据格式不一致的问题
  6. Android 项目在Eclipse中的目录结构
  7. 如何用jQuery获得radio的值
  8. Scheme学习系列一 :源码安装Gambit
  9. 32、[源码]-AOP原理-创建AOP代理
  10. 博图安装msi失败_博途,V13,安装出现如此问题如何解决
  11. 自动化测试之路 —— Appium使用教程
  12. 汽车扭杆弹簧式悬架系统设计-轿车扭杆弹簧式悬架设计方案
  13. 金蝶与旺店通集成解决方案(金蝶为主)
  14. python问题 Traceback (most recent call last)
  15. B2C网关支付方案介绍
  16. ZenTao不支持Win8.1问题解决
  17. 云计算开发技术Python自动化运维开发实战二
  18. Devops实现之jenkins (二)
  19. 20182316胡泊 第2,3周学习总结
  20. Coursehero解锁Coursehero UnlockCoursehero查答案chegg查题下载

热门文章

  1. Redis开发与运维笔记_1 初识2 API
  2. 图解OKR实例--让你写OKR不用愁
  3. 掌握ARM芯片时钟体系
  4. 微信小程序分类及开发成本
  5. UE4_拉近拉远控制某一类Actor的显示与隐藏
  6. android足球经理,分享个安卓版本的足球经理2021(FMT2021),可以安装在手机或者平板上...
  7. 全角转半角,JAVA对中文的处理
  8. ! undefined control sequence \begin{the bibliography}{0}的解决方法
  9. AD19 打印丝印层
  10. 链表相关操作:创建链表、遍历链表、求链表长度、链表中删除一个节点、链表中插入一个节点、反转单链表...