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 原理的更多相关文章

  1. Netty 工具类 —— HashedWheelTimer 讲解

    一.前言 首先有一篇超时任务的实战分析,文章简短精炼明了,阐述了,为什么要用HashedWheelTimer. https://chuansongme.com/n/1650380646616 看完后, ...

  2. HSF的原理分析

    转自:http://blog.csdn.net/qq_16681169/article/details/72512819 一.HSF的基本概念 HSF全称为High-Speed Service Fra ...

  3. HashedWheelTimer

    HashedWheelTimer 是根据 Hashed and Hierarchical Timing Wheels: Data Structuresfor the Efficient Impleme ...

  4. dubbo 序列化机制之 hessian2序列化实现原理分析

    对于远程通信,往往都会涉及到数据持久化传输问题.往大了说,就是,从A发出的信息,怎样能被B接收到相同信息内容!小点说就是,编码与解码问题! 而在dubbo或者说是java的远程通信中,编解码则往往伴随 ...

  5. Dubbo原理和源码解析之服务暴露

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

  6. kafka时间轮的原理(一)

    概述 早就想写关于kafka时间轮的随笔了,奈何时间不够,技术感觉理解不到位,现在把我之前学习到的进行整理一下,以便于以后并不会忘却.kafka时间轮是一个时间延时调度的工具,学习它可以掌握更加灵活先 ...

  7. Rust 实现Netty HashedWheelTimer时间轮

    目录 一.背景 二.延迟队列-时间轮 三.Netty 时间轮源码分析 四.Rust实现HashedWheelTimer 五.总结思考 一.背景 近期在内网上看到一篇文章,文中提到的场景是 系统自动取消 ...

  8. netty系列之:HashedWheelTimer一种定时器的高效实现

    目录 简介 java.util.Timer java.util.concurrent.ScheduledThreadPoolExecutor HashedWheelTimer 总结 简介 定时器是一种 ...

  9. 奇异值分解(SVD)原理与在降维中的应用

    奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...

随机推荐

  1. C# 给某个方法设定执行超时时间 C#如何控制方法的执行时间,超时则强制退出方法执行 C#函数运行超时则终止执行(任意参数类型及参数个数通用版)

    我自己写的 /// <summary> /// 函数运行超时则终止执行(超时则返回true,否则返回false) /// </summary> /// <typepara ...

  2. 一个服务器上面配置多个IP ,实现指定IP的域名请求

    //配置多个IP命名using System.Net; //********************************************************************** ...

  3. 不是技术牛人,如何拿到国内IT巨头的Offer(转载)

    转载的文章,中间有几段需要去学习. byvoid 面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些牛人,NOI金牌,开源社区名人,三年级开始写Basic-在跪拜之余我们不禁要想,和 ...

  4. [ActionScript 3.0] AS3.0 简单封装Socket的通信

    Socket服务器 package com.controls.socket { import com.models.events.AppEvent; import com.models.events. ...

  5. Codeforces 723e [图论][欧拉回路]

    /* 不要低头,不要放弃,不要气馁,不要慌张. 题意: 给你一个有n个点,m条边的无向图,给每条边规定一个方向,使得这个图变成有向图,并且使得尽可能多的点入度与出度相同. 输出有多少个这样的点并且输出 ...

  6. 【解决】SharePoint外部列表保存的日期/时间值不正确

    [问题描述]: 在SharePoint中创建一个外部列表后,通过工作流或直接通过外部列表中的新增向外部列表添加数据项.通过外部列表或数据库查看添加的数据项时发现日期类型字段的值都不正确,像是差了若干个 ...

  7. eclipse 工程默认编码修改 JSP编码修改

    1. Window->Preferences->General->Workspace->Text file encoding 将其改为UFT-8  新建的文件即为UTF-8编码 ...

  8. 黑马程序员_ C语言基础(一)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 开发过程: 编写->编译(只编译源文件,编译成*.o  只会检测语法是否合理,不会检测函数是 ...

  9. Mono addin 学习笔记 2

    下面分析用xml描述文件的方式来进行插件定义 定义扩展点如下: public interface ISnippetProvider { string GetText (string shortcut) ...

  10. iframe中的js

    iframe之间的js是不能相互访问的,iframe和父窗体之间的js也是不能相互访问的