HashedWheelTimer 原理
HashedWheelTimer 是根据
Hashed and Hierarchical Timing Wheels: Data Structures
for the Efficient Implementation of a Timer Facility
这篇论文做出来的.
HashedWheelTimer 主要用来高效处理大量定时任务, 他的原理如图

可以将 HashedWheelTimer 理解为一个 Set<Task>[] 数组, 图中每个槽位(slot)表示一个 Set<Task>
HashedWheelTimer 有两个重要参数
tickDuration: 每 tick 一次的时间间隔, 每 tick 一次就会到达下一个槽位
ticksPerWheel: 轮中的 slot 数
上图就是一个 ticksPerWheel = 8 的时间轮, 假如说 tickDuration = 100 ms, 则 800ms 可以走完一圈
在 timer.start() 以后, 便开始 tick, 每 tick 一次, timer 会将记录总的 tick 次数 ticks
我们加入一个新的超时任务时, 会根据超时的任务的超时时间与时间轮开始时间算出来它应该在的槽位.
例如 timer.newTask(new Task(10, TimeUnit.SECONDS));
表示加入一个 10s 后超时的任务, 那么, 先计算他应该在的槽位
// deadline = 当前时间 + 任务延迟 - timer启动时间 = timer启动到任务结束的时间
long deadline = System.currentTime() + timeout - timerStartTime; // calculated = tick 次数
long calculated = deadline / tickDuration;
// tick 目前已经 tick 过的次数
final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past.
// 算出任务应该插入的 wheel 的 slot, slotIndex = tick 次数 & mask, mask = wheel.length - 1, 默认即为 511
stopIndex = (int) (ticks & mask);
// 计算剩余的轮数, 只有 timer 走够轮数, 并且到达了 task 所在的 slot, task 才会过期
remainingRounds = (calculated - tick) / wheel.length;
其中 stopIndex 为它所在的槽位
remainingRounds 为它从 timer 启动时应该经过的轮数
当 timer tick 到 task 所在的槽位, 并且这个槽位的 remainingRounds <= 0 , 则说明这个 task 超时, 然后执行超时任务, 否则 remainingRounds--
------------------------------------------------------
为什么要使用时间轮的环形结构? 因为环形结构可以根据超时时间的 hash 值(这个 hash 值实际上就是ticks & mask)将 task 分布到不同的槽位中, 当 tick 到那个槽位时, 只需要遍历那个槽位的 task 即可知道哪些任务会超时(而使用线性结构, 你每次 tick 都需要遍历所有 task), 所以, 我们任务量大的时候, 相应的增加 wheel 的 ticksPerWheel 值, 可以减少 tick 时遍历任务的个数.
详细代码参考 Netty 的实现:https://github.com/netty/netty/blob/master/common/src/main/java/io/netty/util/HashedWheelTimer.java
HashedWheelTimer 原理的更多相关文章
- Netty 工具类 —— HashedWheelTimer 讲解
一.前言 首先有一篇超时任务的实战分析,文章简短精炼明了,阐述了,为什么要用HashedWheelTimer. https://chuansongme.com/n/1650380646616 看完后, ...
- HSF的原理分析
转自:http://blog.csdn.net/qq_16681169/article/details/72512819 一.HSF的基本概念 HSF全称为High-Speed Service Fra ...
- HashedWheelTimer
HashedWheelTimer 是根据 Hashed and Hierarchical Timing Wheels: Data Structuresfor the Efficient Impleme ...
- dubbo 序列化机制之 hessian2序列化实现原理分析
对于远程通信,往往都会涉及到数据持久化传输问题.往大了说,就是,从A发出的信息,怎样能被B接收到相同信息内容!小点说就是,编码与解码问题! 而在dubbo或者说是java的远程通信中,编解码则往往伴随 ...
- Dubbo原理和源码解析之服务暴露
github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...
- kafka时间轮的原理(一)
概述 早就想写关于kafka时间轮的随笔了,奈何时间不够,技术感觉理解不到位,现在把我之前学习到的进行整理一下,以便于以后并不会忘却.kafka时间轮是一个时间延时调度的工具,学习它可以掌握更加灵活先 ...
- Rust 实现Netty HashedWheelTimer时间轮
目录 一.背景 二.延迟队列-时间轮 三.Netty 时间轮源码分析 四.Rust实现HashedWheelTimer 五.总结思考 一.背景 近期在内网上看到一篇文章,文中提到的场景是 系统自动取消 ...
- netty系列之:HashedWheelTimer一种定时器的高效实现
目录 简介 java.util.Timer java.util.concurrent.ScheduledThreadPoolExecutor HashedWheelTimer 总结 简介 定时器是一种 ...
- 奇异值分解(SVD)原理与在降维中的应用
奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...
随机推荐
- Perl Sort函数用法总结和使用实例
一) sort函数用法 sort LISTsort BLOCK LISTsort SUBNAME LIST sort的用法有如上3种形式.它对LIST进行排序,并返回排序后的列表.假如忽略了SUBNA ...
- php利用zookeeper作dispatcher服务器
===== https://blog.eood.cn/php_share_memory 最常见的apc 可以缓存php的opcode提高应用的性能,可以在同个php-fpm进程池间共享数据 常见功能: ...
- Electron实战:创建ELectron开发的window应用安装包
前言:研究electron自动更新的时候,在electron的官方文档auto-updater 中,提到了在几个平台mac,Linux,windows下electron 的自动更新方法,其中winds ...
- JSON库之性能比较:JSON.simple VS GSON VS Jackson VS JSONP
从http://www.open-open.com/lib/view/open1434377191317.html 转载 Java中哪个JSON库的解析速度是最快的? JSON已经成为当前服务器与WE ...
- linux 平均负载 load average 的含义
load average 的含义 平均负载(load average)是指系统的运行队列的平均利用率,也可以认为是可运行进程的平均数. 以路况为例, 单核CPU.单车道 情况如下: 0.00-1. ...
- 静态修饰符(关键字static)
1.Static修饰的方法或变量通常称为类方法和类属性 2.静态方法中不能使用this和super关键字,也不能做为局部变量使用 3.在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成 ...
- Unknow Unknow
Unknow Unknow,讲的大概意思是:你不知道这事情的时候,那么请不要轻易下任何结论.例如,这个太难了,放弃吧.嗯,这个是捷径.而最后却是,困难的路越走越容易,容易的路越走越难.只是一种常见的现 ...
- winform客户端向web地址传参,怎样去接收参数。
在web端定义js方法去接收客户端传递过来的参数,具体就是获取地址中?后的数据,各个参数用&分割,存储于数组中,获取. 具体如下: //定义获取地址中参数的方法 function GetReq ...
- CSS+HTML网页设计与布局(学习笔记1)
1.在宽度未知时,使div块居中,可以添加以下属性: display:table;margin:0 auto;
- Ubuntu上安装MongoDB(译)
add by zhj:直接从第四步开始就可以了,而且安装好MongoDB后会自动启动的,不必自己去执行启动命令 原文:https://docs.mongodb.com/manual/tutorial/ ...