Netty-时间轮

Netty-时间轮

归档

  • GitHub: Netty-时间轮

参考

  • Netty-时间轮

说明

  • 其实 Netty 框架并没有使用,其可做学习算法原理的参考

单元测试

public class HashedWheelTimerTest2 {public static void main(String[] args) {System.out.println("---------> " + LocalTime.now());Timer timer = new HashedWheelTimer(); // sign_o_001Timeout timeout1 = timer.newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) {System.out.println("timeout1: " + LocalTime.now());}}, 10, TimeUnit.SECONDS);if (!timeout1.isExpired()) {timeout1.cancel(); // 取消任务}timer.newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws InterruptedException {System.out.println("timeout2: " + LocalTime.now());Thread.sleep(5000); // 占用 5 s,后面的任务会被延后}}, 1, TimeUnit.SECONDS);timer.newTimeout(new TimerTask() { // sign_c_001@Overridepublic void run(Timeout timeout) {System.out.println("timeout3: " + LocalTime.now());System.out.println(timeout.timer()); // 即:sign_o_001System.out.println(timeout.task().getClass()); // 即:sign_c_001}}, 3, TimeUnit.SECONDS);System.out.println("timer -> " + timer);System.out.println("---------> " + LocalTime.now());}
}

原理

类结构

  • io.netty.util.HashedWheelTimer
/*** 时间轮 */
public class HashedWheelTimer implements Timer {private final Worker worker = new Worker(); // 任务执行体private final Thread workerThread;          // 任务线程private final long tickDuration;            // 时针每次 tick 的时间,相当于时针间隔多久走到下一个 slotprivate final HashedWheelBucket[] wheel;    // 槽位数组private final Queue<HashedWheelTimeout> timeouts = PlatformDependent.newMpscQueue(); // MPSC 队列,方便添加处理(用于削峰) sign_f_001private final Queue<HashedWheelTimeout> cancelledTimeouts = PlatformDependent.newMpscQueue(); // 记录取消的,方便移除private final AtomicLong pendingTimeouts = new AtomicLong(0); // 记录等待的任务数/** 槽位 */private static final class HashedWheelBucket {private HashedWheelTimeout head;    // 头private HashedWheelTimeout tail;    // 尾}/** 任务封装 */private static final class HashedWheelTimeout implements Timeout, Runnable {private final TimerTask task;   // 要执行的任务体private final long deadline;    // 终止时间戳long remainingRounds;           // 剩余轮数HashedWheelTimeout next;        // 与 prev 组成双向链HashedWheelTimeout prev;}   
}

调用链

  • io.netty.util.HashedWheelTimer
/*** 时间轮 */
public class HashedWheelTimer implements Timer {/** 添加任务 */@Overridepublic Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {... // 省略校验start(); // 启动线程(如果还没启动的话)long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; // 计算终止时间(startTime 一般为 1)... // 省略 deadline 溢值处理HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);timeouts.add(timeout); // 添加到削峰队列 sign_f_001return timeout;}
}
  • io.netty.util.HashedWheelTimer.Worker
    /** 任务执行体 */private final class Worker implements Runnable {private final Set<Timeout> unprocessedTimeouts = new HashSet<Timeout>(); // 方便 stop() 后记录并返回private long tick; // 走时计数@Overridepublic void run() {... // 省略其他处理do {final long deadline = waitForNextTick();    // 计算并等待if (deadline > 0) {int idx = (int) (tick & mask);  // 计算要处理的槽位索引processCancelledTasks();        // 清空被取消的任务HashedWheelBucket bucket = wheel[idx];transferTimeoutsToBuckets();    // 将队列中的任务转移到相应的槽位里bucket.expireTimeouts(deadline);// 执行槽位里面的任务 sign_m_101tick++; // 计数加 1}} while (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_STARTED); // ... // 省略 stop 处理}// 计算并等待private long waitForNextTick() {long deadline = tickDuration * (tick + 1);for (;;) {final long currentTime = System.nanoTime() - startTime;long sleepTimeMs = (deadline - currentTime + 999999) / 1000000;if (sleepTimeMs <= 0) { // 小于 0 表示不用等待if (currentTime == Long.MIN_VALUE) {return -Long.MAX_VALUE; // 返回最小值,表示后面的逻辑:任务都执行} else {return currentTime;     // 返回当前时间用于参考}}... // 省略 Windows 平台处理try {Thread.sleep(sleepTimeMs);  // 线程睡眠} ... // catch 中断异常处理}}// 转移任务private void transferTimeoutsToBuckets() {for (int i = 0; i < 10_0000; i++) {HashedWheelTimeout timeout = timeouts.poll();... // 省略无新增的任务或任务被取消的处理long calculated = timeout.deadline / tickDuration;timeout.remainingRounds = (calculated - tick) / wheel.length; // 第几轮数final long ticks = Math.max(calculated, tick);int stopIndex = (int) (ticks & mask); // 槽位索引HashedWheelBucket bucket = wheel[stopIndex];bucket.addTimeout(timeout);}}}
  • io.netty.util.HashedWheelTimer.HashedWheelBucket
    /** 槽位 */private static final class HashedWheelBucket {/** 执行任务 sign_m_101 */public void expireTimeouts(long deadline) {HashedWheelTimeout timeout = head;while (timeout != null) {HashedWheelTimeout next = timeout.next;if (timeout.remainingRounds <= 0) {     // 轮数为 0 或小于 0,才执行任务next = remove(timeout);if (timeout.deadline <= deadline) { // 小于当前时间(正常流程)timeout.expire();               // 执行任务 sign_m_201} ... // else 处理(状态不对,抛异常),一般不会发生} else if (timeout.isCancelled()) {next = remove(timeout);} else {timeout.remainingRounds--;          // 减任务轮数}timeout = next;}}}
  • io.netty.util.HashedWheelTimer.HashedWheelTimeout
    /** 任务封装 */private static final class HashedWheelTimeout implements Timeout, Runnable {/** 执行任务 sign_m_201 */public void expire() {if (!compareAndSetState(ST_INIT, ST_EXPIRED)) {return; // 可能已取消}try {timer.taskExecutor.execute(this); // 执行具体的任务} catch (Throwable t) {... // 任务执行异常,只作日志记录(warn 级别)}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/14233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多联机分户计费控制系统

中央空调多联机分户计费控制系统&#xff0c;针对国内常见几种品牌的多联机空调系统实行&#xff0c;远程控制与计费管理。系统采用MQTT网络协议&#xff0c;以订阅/发布模式实行设备感知&#xff0c;实现对室外机、室内机的状态监测、实时故障报警、累计分摊费用的实时数据传导…

AI - 各类AI针对Excel分析对比

一个水果销量表&#xff0c;Excel包含多个年份sheet&#xff0c;需要提取某个品种的水果每年的销量&#xff0c;看看几个AI的分析结果吧 1、文心一言3.5&#xff08;不支持Excel&#xff09; 不支持上传Excel文件 2、 通义千问2.5&#xff08;完成★&#xff09; 顺利完成…

C++-函数

函数&#xff08;Function&#xff09;&#xff1a;是一个提前封装好的、可重复使用的、完成特定功能的独立代码单元。 特点&#xff1a;提前封装、可重复使用的、完成特定功能 将针对特定功能的、有重复使用需求的代码&#xff0c;提前封装到函数内&#xff0c; 在需要的时候…

Linux(openEuler22.03) 定时备份任务 解决方案

目录 定时备份与清理服务环境需求概述步骤详解1. 配置 rsyncd 服务在 backup 服务器上配置 rsyncd 2. 在 nfs01 和 web01 上配置备份脚本脚本&#xff1a;backup_configs.sh配置定时任务 3. 在 backup 服务器上配置同步和清理脚本脚本&#xff1a;cleanup_backups.sh配置定时任…

游戏陪玩/在线租号/任务系统网站源码

源码介绍 游戏陪玩系统/在线租号系统/小姐姐陪玩任务系统/网游主播任务威客平台源码/绝地吃鸡LOL在线下单/带手机端/声优线上游戏任务系统网站源码 界面美观,功能齐全,已对接支付,安装教程放源码压缩包里了! 界面截图 源码下载 https://download.csdn.net/download/huayula…

【计算机网络原理】浅谈应用层协议的自定义和传输层UDP协议的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

如何在cPanel面板中开启双因素身份验证

本周有一个客户&#xff0c;购买Hostease的主机&#xff0c; 客户购买的是Linux虚拟主机&#xff0c;带cPanel面板的。询问我们的在线客服&#xff0c;如何加强他的cPanel的安全性。cPanel的双因素身份验证功能可以帮助帮客户加固安全性。 双因素身份验证(2FA)是一种增强安全性…

【虚拟机软件】 VMware Workstation Pro 17 新建 Linux 虚拟机教程(CentOS 7 版本)

文章目录 下载安装 VMware Workstation Pro 17 软件下载 Linux 的 ISO 映像文件Linux版本选择 新建虚拟机准备配置新建安装 后续设置文章导航 我是一名立志把细节说清楚的博主&#xff0c;欢迎【关注】&#x1f389; ~ 原创不易&#xff0c; 如果有帮助 &#xff0c;记得【点赞…

slam14讲(第8讲、前端里程计)LK光流、直接法

直接法的引出 因为第7讲大部分都是讲特征点法&#xff0c;通过提取orb特征点和点的描述子&#xff0c;来构建两帧图像之间的特征点对应关系。这种方法会有缺点&#xff1a; 关键点和描述子提取计算耗时&#xff0c;如果相机的频率高&#xff0c;则slam算法大部分耗时被占。特…

com.alibaba.fastjson.JSONObject循环给同一对象赋值会出现“$ref“:“$[0]“现象问题

1、问题描述 有些场景下&#xff0c;我们会选择用JSONObject代替Map来处理业务逻辑&#xff0c;但是使用JSONObject时有一个需要注意的地方&#xff1a;在处理JSONObject对象时&#xff0c;引用的com.alibaba.fastjson.JSONObject&#xff0c;在一个集合中&#xff0c;循环给这…

【MySQL精通之路】InnoDB(10)-行格式

目录 1.表数据结构 1.1 聚集索引数据结构 1.2 辅助索引数据结构 2.行格式 2.1 REDUNDANT行格式 2.2 REDUNDANT存储特性 2.3 COMPACT行格式 2.4 COMPACT存储特性 2.5 DYNAMIC行格式 2.6 DYNAMIC存储特性 2.7 COMPRESSED行格式 2.8 COMPRESSED存储特性 3.定义表格的…

数组-区间合并

一、题目描述 二、题目思路 这里提供满足基本要求的解题思路&#xff1a; 1.先对列表内按照start大小升序排序&#xff0c;这里创建Comparator接口的实现类&#xff0c;重写compare方法。 2.遍历intervals&#xff0c;设置laststart、lastend两个变量与当前区间相比较&#…

Ansible实战YAML语言完成apache的部署,配置,启动全过程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f3dd;️Ansible专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年5月24日15点59分 目录 &#x1f4af;趣站推荐&#x1f4af; &#x1f38a;前言 ✨️YAML语言回顾 &#x1f386;1.编写YAML文…

centos 安装nginx 并配置https ssl

进入你要安装的目录 一般是/usr/local/ wget https://nginx.org/download/nginx-1.24.0.tar.gz解压安装包&#xff1a;使用以下命令解压下载的Nginx安装包&#xff1a; tar -zxvf nginx-1.24.0.tar.gz在编译和安装Nginx之前&#xff0c;确保您的系统上已安装了必要的编译工具和…

flume channel和interceptor简介及官方用例

一、Flume Channels channel是在代理上暂存事件的存储库。Source 添加事件&#xff0c;Sink 将其删除。 1、Memory Channel 事件存储在具有可配置最大大小的内存中队列中。它非常适合需要更高吞吐量的流&#xff0c;但在agent发生故障时会丢失暂存数据 Property Name Defau…

k近邻和kd树

K近邻 选取k值的时候可以采用交叉验证的方法 一般采用欧氏距离 kd树 采用树这个特殊的数据结构来实现k近邻算法 先假设是二维的情况 下面讲解kd树的完整构造过程 找这个中位数是按照每棵子树来创建的 前提是已经有了一棵kd树,然后来一个实例点

java组合设计模式Composite Pattern

组合设计模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性。 // Component - 图形接口 interface Graphic {void draw()…

Python UDP编程简单实例

TCP是建立可靠的连接&#xff0c;并且通信双方都可以以流的形式发送数据。 相对于TCP&#xff0c;UDP则是面向无连接的协议&#xff0c;不需要建立连接&#xff0c;只需要知道对方IP地址和端口号&#xff0c;就可以直接发送数据包。但是只管发送不保证到达。 虽然UDP传输数据…

Docker快速部署Seata的TC服务以及微服务引入Seata教程

目录 一、使用docker部署Seata的TC服务 1、拉取TC服务镜像 2、创建并运行容器 ​3、修改配置文件 4、在Nacos中添加TC服务的配置 5、重启TC服务 二、微服务集成Seata 1、引入依赖 2、修改配置文件 Seata是阿里的一个开源的分布式事务解决方案&#xff0c;能够为分布…

STM32学习和实践笔记(31):输入捕获实验

1.输入捕获介绍 在定时器中断实验章节中我们介绍了通用定时器具有多种功能&#xff0c;输入捕获就是其中一种。STM32F1除了基本定时器TIM6和TIM7&#xff0c;其他定时器都具有输入捕获功能。输入捕获可以对输入的信号的上升沿&#xff0c;下降沿或者双边沿进行捕获&#xff0c;…