当前位置: 首页 > news >正文

时间轮定时器HashedWheelTimer

HashedWheelTimer 是 Netty 框架提供的一种高效定时任务调度器,基于 哈希轮(Hashed Wheel) 数据结构实现,专门用于处理大量短延迟的定时任务,性能优于 JDK 原生的 Timer 或 ScheduledExecutorService

一、核心原理:哈希轮(Hashed Wheel)

可以把哈希轮想象成一个 “时钟表盘”

  • 轮盘(Wheel):一个数组,每个元素称为 “槽位(Bucket)”,每个槽位对应一个固定的时间间隔(如 10ms)。
  • 指针(Tick):轮盘会按固定频率(如每 10ms)转动一次,指针指向当前需要处理的槽位。
  • 任务(Task):提交的定时任务会根据延迟时间被分配到对应槽位,当指针转到该槽位时,任务被触发执行。

例如:

  • 若轮盘有 10 个槽位,每个槽位代表 10ms,则一轮(转完所有槽位)耗时 100ms。
  • 一个延迟 35ms 的任务,会被分配到第 3 个槽位(35ms ÷ 10ms = 3.5 → 向下取整到第 3 槽),指针转动 3 次后执行。

二、关键特性

  1. 高效处理大量任务
    传统定时器(如 Timer)通过优先级队列存储任务,每次添加 / 执行任务都需要排序,时间复杂度为 O (logN)。
    哈希轮通过数组直接定位槽位,添加任务的时间复杂度为 O (1),适合高并发场景(如同时提交数万定时任务)。

  2. 单线程驱动
    内部只有一个工作线程(Worker Thread)负责 “转动轮盘” 和触发任务,避免多线程竞争开销。
    ⚠️ 注意:任务执行逻辑若耗时较长,会阻塞后续任务,建议通过线程池异步执行(如你代码中的 appTaskExecutor)。

  3. 时间精度可控
    精度由 槽位间隔(tick duration) 决定(如 10ms 间隔的轮盘,最小延迟精度为 10ms)。
    间隔越小,精度越高,但轮盘转动频率越高,CPU 消耗越大(需根据业务平衡)。

三、核心参数(构造函数)

public HashedWheelTimer(ThreadFactory threadFactory,    // 线程工厂(用于创建工作线程)long tickDuration,             // 槽位间隔(每个槽位的时间,如 10ms)TimeUnit unit,                 // 槽位间隔的时间单位int ticksPerWheel,             // 轮盘槽位数量(建议为 2 的幂,如 512、1024)boolean leakDetection,         // 是否启用内存泄漏检测long maxPendingTimeouts        // 最大等待任务数(超过则拒绝)
)

常用简化构造

// 示例:槽位间隔 10ms,槽位数量 512
HashedWheelTimer timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS, 512);

四、基本使用流程

  1. 创建定时器

    HashedWheelTimer timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS, 512);
    
  2. 提交延迟任务
    通过 newTimeout 方法提交任务,返回 Timeout 对象(任务句柄,可用于取消任务):

    // 延迟 3 秒执行任务
    Timeout timeout = timer.newTimeout(// 任务逻辑(TimerTask 接口,Lambda 简化实现)timeout -> {System.out.println("任务执行:" + System.currentTimeMillis());},3,          // 延迟时间TimeUnit.SECONDS  // 时间单位
    );
    
  3. 取消任务(若任务未执行)

    if (!timeout.isExpired()) {  // 判断任务是否已执行timeout.cancel();        // 取消任务
    }
    
  4. 关闭定时器(释放资源)

    timer.stop();  // 停止工作线程,释放资源
    

五、适用场景

  • 短延迟、高并发任务:如 RPC 超时控制、连接心跳检测、短期缓存过期清理。
  • 需要低延迟调度:相比 ScheduledExecutorService,哈希轮的调度延迟更低。

不适用场景

  • 长时间延迟任务(如几小时后执行):会占用轮盘槽位,浪费资源。
  • 任务执行耗时较长:会阻塞单工作线程,需配合线程池使用。

六、与 JDK 定时器的对比

特性HashedWheelTimerScheduledExecutorService
数据结构哈希轮(数组)优先级队列
添加任务复杂度O(1)O(logN)
线程模型单线程驱动多线程(可配置核心线程数)
精度控制由槽位间隔决定(如 10ms)毫秒级(理论精度更高)
大量任务性能优秀(适合高并发)一般(队列排序开销大)

总结

HashedWheelTimer 是 Netty 针对 “大量短延迟定时任务” 设计的高效解决方案,通过哈希轮数据结构实现了 O (1) 级别的任务添加效率,适合网络框架、中间件等高性能场景。使用时需注意:

  • 任务执行逻辑应尽可能短(或通过线程池异步执行)。
  • 根据业务需求合理设置槽位间隔和数量(平衡精度与性能)。
  • 及时调用 stop() 释放资源,避免线程泄漏。
http://www.dtcms.com/a/354178.html

相关文章:

  • WSL设置静态IP
  • window程序打包
  • Libvio网站与客户端访问故障排查指南(专业版)
  • 什么是低空经济?
  • JMeter 5.3 性能测试:文件下载脚本编写与导出文件接收完整指南
  • QT鼠标事件中的QMouseEvent :e
  • 深度学习---卷积神经网络CNN
  • PLC_博图系列☞基本指令”S_ODT:分配接通延时定时器参数并启动“
  • HTML5超详细学习内容
  • 程序(进程)地址空间(1)
  • 基于MATLAB/Simulink的单机带负荷仿真系统搭建
  • LeetCode-23day:技巧经典
  • 疯狂星期四文案网第52天运营日记
  • 野火STM32Modbus主机读取寄存器/线圈失败(二)-解决CRC校验错误
  • 让ai写一个类github首页
  • Web前端之JavaScript时间体系全解析、performance、Date、now
  • Go语言循环性能终极对决:for vs range 深度剖析
  • 如何用Postman做接口测试?
  • k8s中的服务(Service),详细列举
  • JavaSE:类和对象2
  • Redis集群介绍——主从、哨兵、集群
  • 单兵图传设备如何接入指挥中心平台?国标GB/T28181协议的20位ID有何含义?如何进行配置?
  • [手写系列]Go手写db — — 第二版
  • spring-boot-test与 spring-boot-starter-test 区别
  • 前端架构设计模式与AI驱动的智能化演进
  • 嵌入式学习日志————USART串口协议
  • 【开发便利】让远程Linux服务器能够访问内网git仓库
  • 目标检测基础
  • [系统架构设计师]论文(二十三)
  • 控制系统仿真之时域分析(二)