前言 之所以写这篇文章,是在一篇博客中看到了时间轮定时器这个东西,感觉很是惊艳,https://www.cnblogs.com/zhongwencool/p/timing_wheel.html。...*max_timer 表示定时器所能接受的分钟时间间隔 */ int InitTimerWheel(int step,int max_min); int AddTimer(int interval...} else { InsertTimer(item->interval - diff_ms, *item); } } return 0; } 这里实现的是一个毫秒到分钟级别的三成时间轮定时器...初始化一个三层时间轮:毫秒刻盘:1000/step_ms 个MSList, 秒刻盘:60个SList, 时刻盘:max_min个MinList; 1.2....最高层:MinTick跳一轮(max_min格),MinTick复位至0,一个时间轮完整周期完成. 2.事件原理说明: 2.1.
时间轮 简述 顾名思义,时间轮就像一个轮子,在转动的时候外界会指向轮子不同的区域,该区域就可以被使用。...因此只要将不同时间的定时器按照一定的方法散列到时间轮的不同槽(即时间轮划分的区域)之中,就可以实现在运转到某个槽时,进行判断该定时器是否已经到达运行时间(需要判断是由于有的定时器并非在这一圈就需要运行,...所以时间轮简单来说就是散列 + 链表,这样与使用升序链表相比,散列可以直接定位要插入的槽所在位置,可以提高添加定时器的效率,由O(N)到了O(1)。...对实现时间轮来说,最主要的还是链表的操作是否熟练,当然也主要是双向链表的添加与删除。 代码分析 记录定时器的时间信息,从而获取在时间轮中槽的位置,以及在多少圈之后被触发。...,时间轮采用双向链表 class TwTimer { public: int rotation; // 定时器转多少圈后生效 int time_slot; // 记录定时器属于时间轮的哪个时间槽 client_data
时间轮实现 Linux定时器分为低精度定时器和高精度定时器两种类型,内核对其均有实现。本文讨论的是我们在应用程序开发中比较常见的低精度定时器。...作为常用的基础组件,定时器常用的几种实现方法包括:基于排序链表实现、基于小根堆实现、基于红黑树实现、基于时间轮实现。本文讲解的是时间复杂度最优,也是linux内核采用的基于时间轮的实现方式。...之所以没法做到O(1)的复杂度,究其原因是所有定时器节点挂在一条链表(或一棵树)上。时间轮算法的核心思路是将定时器散列到多条链上,是典型的空间换时间的策略。...下文从单个时间轮出发讲解,逐步扩展至linux实现定时器所采用的多级时间轮算法。...Linux时间轮定时器算法的关键在于添加定时器操作和时间轮进位迁移链表操作。先来说添加定时器。添加定时器的关键又在于知道每个时间轮每一个刻度所能表示的到期时间的范围。
看完了《linux高性能服务器编程》对里面的定时器很感兴趣。书中提到三种定时器,分别是:基于升序链表的定时器,基于时间轮的定时器,基于时间堆的定时器。...三种定时器的实现书中均是给了C++代码,不过我对C++不太感兴趣,虽然现在在做C++开发,因此写了C版本的。书中定时器只给了封装的定时器类,没有给调用层代码,我是估摸着写了调用层代码。...说一下时间轮,下面是截的书中的图片 时间轮,像轮子一样滚动定时,每滚一个刻度,指针就走一个滴答,滚完一圈,就进入下一圈。...也就是说,如果我们根据以上参数,同时添加一个15s和一个161s定时器,他们都会随时间轮轮转触发到,只不过指针第一次只想15槽时,判断15s的定时器rotation为0,则触发定时器,然后删除定时器,遍历到...,即时间轮转多少转 //此定时器可以处于当前转,若再加上槽 //即可确定此定时器所处时间轮位置 int rotation; //处于当前时间轮转的第几个槽 int slot; //定时器到时执行的回调函数
C语言定时器实验 实验三 C语言定时器实验 一、实验目的 1.进一步熟悉DSP的中断机制 2.在掌握中断服务程序编写的基础上进一步熟悉定时器的运用 3.进一步掌握如何编写DSP中断服务子程序 二、实验设备...当TIM寄存器中的至递减至0的时候,定时器复位,TIM重新加载PRD寄存器中的值,开始下一轮计数,与此同时,当该寄存器中的值递减至0的时候,产生定时器中断。...四、实验内容 用C语言编写定时器实验:两个灯以不同频率闪烁,并用示波器读频率 五、实验步骤 第一步骤:新建项目fangbo.pjt及编写定时中断文件( Timer.c,vectors.asm,c54_zzh.cmd.../**********************************************/ /* Title: Timer.c */ /* Author: ZZH */ /* Data: 2005...-8-25 */ /**********************************************/ #include #include #include “c54xx.h” #include
对于时间轮来说,我以前写过一篇java版的时间轮算法分析:https://www.luozhiyun.com/archives/59,这次来看看Go语言的时间轮实现,顺便大家有兴趣的也可以对比一下两者的区别...代码实现 因为我们这个Go语言版本的时间轮代码是仿照Kafka写的,所以在具体实现时间轮 TimingWheel 时还有一些小细节: 时间轮的时间格中每个链表会有一个root节点用于简化边界条件。...修剪方法为:currentTime = startMs - (startMs % tickMs); Kafka 中的定时器只需持有 TimingWheel 的第一层时间轮的引用,并不会直接持有其他高层的时间轮...,但每一层时间轮都会有一个引用(overflowWheel)指向更高一层的应用; Kafka 中的定时器使用了 DelayQueue 来协助推进时间轮。...中C的数据,如果C中有数据表示已经到期,那么会先调用advanceClock方法将当前时间 currentTime 往前移动到 bucket的到期时间,然后再调用Flush方法取出bucket中的队列,
时间轮 作用 也是用来作定时器触发任务,只是他更高效,时间复杂度为O(1)。...– 42200(6060*12)秒 时间与每层的索引关系 举个简单的4层时间轮例子(如左上图),假设最小计时单位为1(姑且理解为秒) 时间轮初始为0,那么给定任意时间time,求time落在每层时间轮的索引...从数据结构设计 时间轮是由多个定长数组组成的,我们只需要把事件接在数组中就可以了,由于同一时刻会有多个事件,考虑先添加的事件先执行,使用链表来把事件连接起来,因此时间轮是一个 定长的包含链表的数组 事件添加过程...,并且时间轮涉及到了很多乘法和除法和取余,所以可以考虑使用位运算来替代运行。...完整Demo源码 qt c++代码 版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
头文件:time.h 函数原型:time_t time(time_t * timer) 功 能: 获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从UTC(Coordinated...Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。...然后可以调用localtime将time_t所表示的UTC时间转换为本地时间(我们是+8区,比UTC多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。...; localtime是将时区考虑在内了,转出的当前时区的时间。...但是注意,有些嵌入式设备上被裁减过的系统,时区没有被设置好,导致二者转出来的时间都是0时区的。 版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。
当业务要处理大量的定时任务时,如果每个任务都创建一个Golang原生的timer的话,会占用较多的cpu资源,这类场景,可以用时间轮算法优化timer的资源消耗。...本次介绍一款多级时间轮库antlabs/timer(以下timer特指antlabs/timer库),处理类似场景的优化。...benchmark Golang 1.14对定时器做了优化,每个P维护一个定时器,减少了添加删除任务时的锁竞争,但是和本文介绍的timer库对比起来还是有些耗资源,下面是benchmark的结果: Golang...Benchmark_Stdlib_AddTimer/N-10m-8 7703940 230.8 ns/op 80 B/op 1 allocs/op 总结 timer利用时间轮算法...,通过降低定时器精度的方式,将同一个时间单位内的任务集中存储到一个双向链表,可以一次锁操作处理,减少锁竞争,进而提高性能,对于业务中有大量定时任务,同时对精度要求大于10ms的场景,可以尝试timer库来优化
一、什么是时间轮?...这个时候时间轮就呼之欲出了,下面就是时间轮的表演时间了 我们固定数组的长度为60个格子,每个格子的精度为1s,那么一圈就是60s,如果我有3个任务A、B、C,他们相对于启动轮询线程开始走第一个格子的时间差分...别为3s,50s,55s,那么其对应的格子为 轮询线程只要走到对应A、B、C的格子就可以执行它们了,但是如果我有一个一万秒之后执行的任务D,该怎么办呢?...当然是可以的,假设我有一个任务E是在某点某分某秒执行,那么我们可以定义三个时间轮, 分别是秒时间轮,分时间轮,小时时间轮 秒时间轮:总共60个格子,每格1s 分时间轮:总共60个格子,每格1分钟...30个格子之后,又会把任务E存放到秒时间轮的第20个格子上,等秒时间轮走到第20个格子上之后 就会执行任务,我们管这种时间轮叫做层级时间轮。
如下图所示: 中间的圆轮代表一个时间周期,轮子上的每个节点关联的链表代表该时间点要触发的任务。...常用的有MpscArrayQueue和MpscChunkedArrayQueue,jdk的juc包下的相关并发实现也参考了Mpsc无锁队列. 2.多重时间轮 当时间跨度很大时,提升单层时间轮的 tickDuration...可以减少空转次数,但会导致时间精度变低,层级时间轮既可以避免精度降低,又避免了指针空转的次数。...如果有时间跨度较长的定时任务,则可以交给层级时间轮去调度。...: 原生时间轮是单机的,在分布式和多实例部署的场景中乏力 宕机重新恢复执行,原生时间轮的存储是Mpsc队列,毫无疑问是内存存储,如果出现宕机或者重启,数据是不可恢复的 对于类似订单超时取消的场景,可以考虑时间轮
因为时间轮算法的精度取决于,时间段“指针”单元的最小粒度大小,比如时间轮的格子是一秒跳一次,那么调度精度小于一秒的任务就无法被时间轮所调度。...2.2.带圈数的时间轮 第一种最基础的时间轮中其实缺陷还是挺明显的。例如我设置一个间隔为1分钟,环形队列节点数为60个节点的时间轮。...2.3.多层时间轮 再回头看一下2.2。如果任务的跨度时间很长,那么时间轮将会空转,只有round为0才会进行任务的执行,这个无疑是很消耗cpu的。...三.应用 时间轮的使用在各大框架与中间件中有使用,xxl-job,netty,kafka都对时间轮都自己的实现。思路基本上与删除的时间轮策略一致。 ...四.参考 时间轮在 Kafka 的实践
timewheel Golang实现的时间轮 项目地址 原理 延迟消息的实现 安装 go get -u github.com/ouqiang/timewheel 使用 package main import...即时间轮多久转动一次 // 第二个参数为时间轮槽slot数量 // 第三个参数为回调函数 tw := timewheel.New(1 * time.Second, 3600,...func(data timewheel.TaskData) { // do something }) // 启动时间轮 tw.Start() // 添加定时器...// 第一个参数为延迟时间 // 第二个参数为定时器唯一标识, 删除定时器需传递此参数 // 第三个参数为用户自定义数据, 此参数将会传递给回调函数, 类型为map[interface..., 参数为添加定时器传递的唯一标识 tw.RemoveTimer(conn) // 停止时间轮 tw.Stop() select{} } 版权声明:本文内容由互联网用户自发贡献
时间轮算法 最近工作中使用了Xxl-Job框架来做分布式调度,内部采用了时间轮做整体调度,顺便学习并总结一下。 绝对时间和相对时间 定时任务一般有两种: 1. 约定一段时间后执行。 2....假设我们现在有3个定时任务A、B、C,分别需要在3点、4点和9点执行,我们把它们都转换成绝对时间。 ...最简单的办法就是增大时间轮的长度,可以从12个加到168 (一天24小时,一周就是168小时),那么下周一上午九点就是时间轮的第9个刻度,这周三上午九点就是时间轮的第57个刻度。...但是这样带来的问题时,每次移动刻度的耗时会增加,当时间刻度很小(秒级甚至毫秒级),任务列表有很长,这种方案是不能接受的。 分层时间轮 分层时间轮是这样一种思想: 1....根据这三个任务的调度粒度,可以划分为3个时间轮,月轮、周轮和天轮,初始添加任务时,任务一被添加到天轮上,任务二被添加到周轮,任务三被添加到月轮上。
dubbo-common 包中,有个比较有趣的功能 —— HashedWheelTimer,也就是时间轮。...---- 总结 Dubbo 时间轮,涉及到了大量的多线程开发代码,对学习如何运用多线程有很大的帮助。
时间戳是计算机中记录时间的一种方法,某一时刻的时间戳指的是从 1970 年 1 月 1 日 0 时 0 分 0 秒开始到该时刻总共过了多少秒。...假设一年 12 个月,每个月有 30 天,那么: 一天的时间(秒)为:days = 24×60×60 = 86400 秒; 一个月的时间(秒)为:months = days×30 = 2592000 秒...n 除以一年的时间(秒)years 的商加上 1970 就是具体年份 y,余数再除以一月的时间(秒)months 的商加 1 就是月份 m,再次得到的余数除以一天的时间(秒)days 的商加 1 就是日期.../ 3600 M = n % years % months % days % 3600 / 60 S = n % years % months % days % 3600 % 60 图 1 展示了普通时间值和时间戳...图 1:普通时间值和时间戳(秒单位的值)相互转换 算法描述 代码清单 1:C语言程序源代码(时间戳) #include #include int main( ) { system(“color
二:获取系统日期和系统时间。...一月一日后的天数(0-365),本年第几日,闰年有366日 int tm_isdst 夏令时标志(大于0的值说明夏令时有效,0说明无效,负数说明信息不可用) ¹time - 库函数 描述 C语言当中的库函数...time_t time(time_t *seconds) 注→这个存储的类型是时间类型也就是time_t在我们获取系统日期之前我们需要定义一个时间类型的变量。...返回值 以 time_t 对象返回当前日历时间。...---- ²localtime - 库函数 描述 C 库函数 struct tm *localtime(const time_t *timer) 使用 timer 的值来填充 tm 结构。
时间轮是一种高性能定时器。 时间轮,顾名思义,就是一个基于时间的轮子,轮子划分为多个槽,每个槽代表一个时间跨度,槽的数量*时间跨度等于时间轮可以支持的最大延迟时间。...我们可以把时间轮分级,n+1层时间轮的槽时间跨度为n层时间轮的一圈的总时间跨度,所以当n层时间轮推进一圈时,n+1层时间轮推进一个槽,并且只有第一层时间轮实际处理定时任务,其余n+1层时间轮转动后,都是把当前槽的任务降级挂载到第...例如,我们如图有三级时间轮,一级时间轮每个槽1秒时间跨度,3600槽,即一圈总时间跨度1小时。二级时间轮每个槽1小时时间跨度,24个槽,即一圈总时间跨度1天。...但是也产生了另外一个问题,即n级时间轮推进一圈后,需要等待n+1级时间轮降级后才可以继续推进,如果n+1级时间轮的降级操作很耗时,则会影响n级时间轮的正常推进。...所以一般会采用预热的方式,提前触发n+1级时间轮的降级,解耦多级时间轮之间推进的强关联,保证一级时间轮推进的连续性。
时间轮算法思想 无论通过何种方式实现定时任务队列,最终需要向上层提供如下接口: 添加定时任务; 删除(取走)定时任务; 执行定时任务; 2.1 简单时间轮算法 时间轮算法的核心是:轮询线程不再负责遍历所有任务...如果要将时间精度设为秒,那么整个时间轮将需要 86400 个单位的时间刻度,此时时间轮算法的遍历线程将遇到更大的运行效率低的问题。下面两个小节将着力解决此问题。...2.2 带有 round 的时间轮算法 我们发现,时间轮的时间刻度随着时间精度而增加并不是一个好的问题解决思路。现在,我们将时间轮的精度设置为秒,时间刻度个数固定为 60。...此时时间轮算法的数据结构如下图所示: 这种方式虽然简化了时间轮的刻度个数,但是并没有简化轮询线程运行效率不高的问题。时间轮每次处理一个时间刻度,就需要处理其上任务队列的所有任务。...2.3 分层时间轮算法 分层的时间轮算法在生活中有对应的模型(艺术来源于生活~),那就是水表: 此时,我们有秒、分钟、小时级别的三个时间轮,每一个时间轮分别有 60、60、24 个刻度。
—(线性顺序执行多个task,是从queue中获取task然后执行,如果时间早于当前时间会马上执行任务) package cn.qlq.thread.fourteen; import java.util.Date...,也就是从当前任务执行的开始时间到下次任务开始时间的间隔是20秒) 3....并且在period后重复执行任务,执行时间是从上次任务结束时间开始计算。凡是带period的都会在时间间隔后重复执行。...在有延时和没有延时的情况下,周期性的任务的下次任务开始时间都是相对于上次任务的开始时间进行延迟(这个在并发编程书中说的是有延迟的情况下相对于结束时间,但是自己测的是相对于开始时间) schedule和...scheduleAtFixedRate的区别在于,如果指定开始执行的时间在当前系统运行时间之前,scheduleAtFixedRate会把已经过去的时间也作为周期执行,而schedule不会把过去的时间算上
领取专属 10元无门槛券
手把手带您无忧上云