时间轮算法HashedWheelTimer

news2025/1/11 18:43:16

文章目录

    • 一.HashedWheelTimer是什么?
    • 二.能干什么?为什么需要这个东西?
      • 优点
      • 适用场景
    • 三.怎么用?使用步骤
      • 1.引入pom
      • 2.使用举例
    • 四.时间轮原理
    • 五.使用注意点
      • 1.一个HashedWheelTimer对象只有一个worker线程
      • 2.每次添加的任务只会执行一次
      • 3.时间轮的参数非常重要
      • 4.所有的任务都是顺序串行执行的

一.HashedWheelTimer是什么?

   时间轮是一种非常惊艳的数据结构。其在Linux内核中使用广泛,是Linux内核定时器的实现方法和基础之一。
   换句话说时间轮是一种高效来利用线程资源来进行批量化调度的一种调度模型。把大批量的调度任务全部都绑定到同一个的调度器上面,使用这一个调度器来进行所有任务的管理(manager),触发(trigger)以及运行(runnable)。能够高效的管理各种延时任务,周期任务,通知任务等等
   而HashedWheelTimer则是使用了时间轮这种数据结构,它是Netty内部的一个工具类,最开始主要用来优化I/O超时的检测,本文将详细分析HashedWheelTimer的使用及原理。

二.能干什么?为什么需要这个东西?

优点

      其实笔者认为其最大的优点就是可以在一个线程中动态的添加定时(延时)任务
像我们经常使用Timer,ScheduledExecutorService,Spring的Scheduled这些都是无法做到这一点的,一旦某个线程开始执行某个定时任务,都是无法再去动态添加的

      那某些场景,比如说有很多小的定时任务,难道每一个都去起一个线程处理吗?那数量多的话对程序势必影响很大,浪费资源,这个时候就可以考虑HashedWheelTimer了.

      而在netty中,因为其可能管理上百万的连接,每一个连接都会有很多超时任务。比如发送超时、心跳检测间隔等,如果每一个定时任务都启动一个Timer,不仅低效,而且会消耗大量的资源。所以创造了这个工具类.

适用场景

  1. 订单超时
  2. 分布式锁中为线程续期的看门狗
  3. 心跳检测

三.怎么用?使用步骤

1.引入pom

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.45.Final</version>
</dependency>

2.使用举例

1.构建对象,添加定时任务

        //在一个格子里面的并不会区分的很细,而会依次顺序执行,所以适用于对时间精度要求不高的任务
        //构建时间轮对象
        HashedWheelTimer timer = new HashedWheelTimer(5, TimeUnit.SECONDS, 10);
        //添加定时任务1,延迟2s执行
        timer.newTimeout((TimerTask) timeout -> {
            System.out.println("任务1执行");
            System.out.println("线程名称:"+Thread.currentThread().getName());

        },2,TimeUnit.SECONDS);
        //添加定时任务2,延迟2s执行
        timer.newTimeout((TimerTask) timeout -> {
            System.out.println("任务2执行");
            System.out.println("线程名称:"+Thread.currentThread().getName());
        },5,TimeUnit.SECONDS);

        //等待定时任务执行完毕后,将时间轮内部工作线程停止,这里只是粗略的等待,也可以使用CountDownLatch
        Thread.sleep(10000);

        timer.stop();

2.取消某个定时任务

       //构建时间轮对象
        HashedWheelTimer timer = new HashedWheelTimer(1, TimeUnit.SECONDS, 10);
        //添加定时任务1
        Timeout newTimeout = timer.newTimeout((TimerTask) timeout -> {
            System.out.println("任务1执行");
            System.out.println("线程名称:" + Thread.currentThread().getName());

        }, 5, TimeUnit.SECONDS);

        //现在又想取消掉这个任务
        if(!newTimeout.isExpired()){
            newTimeout.cancel();
        }

四.时间轮原理

   时间轮其实就是一种环形的数据结构,可以想象成时钟,分成很多格子,一个格子代码一段时间(这个时间越短,Timer的精度越高)。并用一个链表表示在该格子上的到期任务,同时一个指针随着时间一格一格转动,并执行相应格子中的到期任务。任务通过取摸决定放入那个格子。如下图所示:
在这里插入图片描述

   假设一个格子是1秒,则整个wheel能表示的时间段为8s,假如当前指针指向2,此时需要调度一个3s后执行的任务,显然应该加入到(2+3=5)的方格中,指针再走3次就可以执行了;如果任务要在10s后执行,应该等指针走完一个round零2格再执行,因此应放入4,同时将round(1)保存到任务中。检查到期任务时应当只执行round为0的,格子上其他任务的round应减1。

再回头看看构造方法的三个参数分别代表

  • tickDuration
    每一tick的时间
  • timeUnit
    tickDuration的时间单位
  • ticksPerWheel
    就是轮子一共有多个格子,即要多少个tick才能走完这个wheel一圈。

五.使用注意点

1.一个HashedWheelTimer对象只有一个worker线程

2.每次添加的任务只会执行一次

3.时间轮的参数非常重要

   比如我这里设置每个格子的时间为6s,添加了两个定时任务,一个延时2s执行,一个延时5s执行,但是最终执行结果是同时执行,因为这两个任务都被分配到第一个格子中,按顺序执行.
   所以时间轮的参数要根据时间情况具体设定

在这里插入图片描述

4.所有的任务都是顺序串行执行的

也就是说上一个任务的异常延时会影响到下一个任务.
比如我这里添加了两个定时任务,第一个延时2s,第二个延时5s,但是因为第一个任务的延时,导致第二个延时了10s才执行.
在这里插入图片描述
所以这里要求时间轮执行的任务都是比较快的, 或者这里可以使用异步任务去处理.

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

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

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

相关文章

rabbitmq基础1——消息中间件概念、Rabbitmq的发展起源和基本组件的作用流程

文章目录一、消息中间件1.1 概念1.2 作用1.2.1 消息队列持久化1.2.2 消息队列分发策略1.2.3 消息队列的高可用和高可靠1.2.3.1 一主多从共享集群1.2.3.2 一主多从同步集群1.2.3.3 多主多从同步集群1.2.3.4 多主转发集群1.2.3.5 Master-slave与Breoker-cluster组合方案1.3 初识A…

实战总结!18种接口优化方案的总结

之前工作中&#xff0c;遇到一个504超时问题。原因是因为接口耗时过长&#xff0c;超过nginx配置的10秒。然后 真枪实弹搞了一次接口性能优化&#xff0c;最后接口从11.3s降为170ms。本文将跟小伙伴们分享接口优化的一些通用方案。 1. 批量思想&#xff1a;批量操作数据库 优化…

Windows环境监控Linux服务器资源grafana+prometheus+mysql_exporter

Windows环境监控Linux服务器资源grafanaprometheusmysql_exporter 1.安装mysql (1)在虚拟机中下载wget命令 yum -y install wget(2)在线下载mysql安装包 wget https://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm(3)安装MySQL rpm -ivh mysql57-communi…

信仰崩了?Preact 开始采用 Vue3 的响应式设计

前言 不知大家有没有听过Preact这个框架&#xff0c;就算没听过Preact那也应该听过React吧&#xff1f; 一字之差&#xff0c;preact比react多了个p&#xff01;&#xff08;听起来咋不像啥好话呢&#xff09; 这个P代表的是 Performance&#xff0c;高性能版React的意思。P…

一篇博客详解朴素贝叶斯解分类问题

目录 回归问题 正则化Regularization 分类问题—类别之间是独立的 为什么不用回归解分类问题以概率的形式解分类问题 抽盒机率→分类机率正态分布覆盖 原理高斯分布函数 极大似然估计求最优参数 朴素贝叶斯法 用同一个协方差三步骤 模型的简化 回归问题 大概内容与之前的类…

工业ESD防静电闸机系统帮助您实现静电监控自如!

如何有效检测、消除静电&#xff0c;对元器件品质进行有效管控&#xff1f;现在工厂常用的设备有腕带接地、电阻测试仪&#xff0c;ESD防静电系统&#xff0c;但是这些都是在我们生产的同时去监控处理掉静电&#xff0c;那么有没有一种能直接从人体根源消除掉静电的系统呢&…

Postman 的简单使用

什么是Postman 在程序开发中用于调试网络程序或者跟踪网页请求。可以对网页进行简单的基本信息调试。Postman最早是作用chrome浏览器插件存在的&#xff0c;但是2018年初Chrome停止对Chrome应用程序的支持。所以现在Postman提供了独立的安装包&#xff0c;不再依赖于Chrome浏览…

MySQL innodb引擎架构分析-Buffer Pool

文章目录系列文章目录前言一、Buffer Pool是什么&#xff1f;二、Buffer Pool是如何工作的&#xff1f;1. free链2. flush链根据脏页的情况(阈值)和相关配置刷新自适应刷脏3. Lru升级链总结参数&#xff1a;innodb_buffer_pool_size参数&#xff1a;innodb_buffer_pool_instanc…

避免重要数据泄露的8种方式

得益于国家的大力支持&#xff0c;我国数字化经济已开启高速发展模式&#xff0c;数据已经成为企业不可或缺的重要资产&#xff0c;相对应的数据安全风险问题也随之而来。 数据泄露不仅给企业带来了财产损失&#xff0c;也给企业带来了极大的声誉威胁。以下是日常生活中企业和…

W公司对接奥迪Audi EDI项目案例

项目背景 奥迪&#xff08;Audi&#xff09;是德国大众汽车集团子公司奥迪汽车公司旗下的豪华汽车品牌&#xff0c;作为高技术水平、质量标准、创新能力、以及经典车型款式的代表&#xff0c;奥迪是汽车品牌之一。公司总部设在德国的英戈尔施塔特&#xff0c;并在中国等许多国…

ASA防火墙高级配置——NAT控制欲NAT豁免

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.NAT控制欲NAT豁免 1.禁用NAT控制 1&#xff09;出站(Outbou…

2021全国高校计算机能力挑战赛(初赛java)(部分)

数据1 input: 4 L G D U 7 L Y C N 2 T G E N 1 T R E P 4 output: 1 1 数据2 input: 6 L G D E 7 L Y C N 4 T G E N 4 T Y E P 3 L Y C N 2 T G D N 3 output: 1 1 package com.第四届校内模拟;import java.util.Scanner;/*** Author Lunau* Create 2022-12-09 18:02* Descri…

使用 ESP-DL 深度学习库基于 ESP32-S3 实现手势识别

人工智能改变了计算机与现实世界交互的方式。过去&#xff0c;人们通过微小的低功率设备和传感器获取数据&#xff0c;并传输至云端进行决策。这样的方式在设备连接性、成本和数据隐私方面带来了一定挑战。相对地&#xff0c;边缘人工智能是在物理设备上另一种处理数据的方式&a…

11.javase_面向对象1

一.面向对象介绍 1.1并不是一个技术&#xff0c;而是一种编程指导思想 1.2以什么形式组织代码&#xff1b;以什么思路解决问题 1.3为什么要用面向对象编程&#xff1a; 因为生活中&#xff0c;我们解决问题时&#xff0c;就是采用这种指导思想去解决的。 所以&#xff0c;我们写…

Codeforces Round #792 (Div. 1 + Div. 2)

比赛链接&#xff1a;Dashboard - Codeforces Round #792 (Div. 1 Div. 2) - Codeforces A: 思维 题意&#xff1a;Alice和Bob在玩游戏&#xff0c;每次等Alice交换两个不同位置的数后&#xff0c;Bob就会删除最后一个位置上的数&#xff0c;当最终只剩下一个数后&#xff0c…

基于对抗互信息学习特征解耦的零样本语音转换|INTERSPEECH 2022

零样本语音转换在转换时只需目标说话人的一段语音&#xff0c;更适合实际应用需求&#xff0c;具有广泛应用前景。 现有工作只考虑内容和音色表征的解耦&#xff0c;没有考虑与语音旋律相关的 韵律 和 音高 表征&#xff0c;导致与音高和韵律相关的信息泄露到音色中。 本文利用…

Flutter - Stack 与 Positioned 层叠布局

1 层叠布局和 Web 中的绝对定位、Android 中的 Frame 布局是相似的 2 子组件可以根据距父容器四个角的位置来确定自身的位置。 3 层叠布局允许子组件按照代码中声明的顺序堆叠起来。 4 Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。 5 Stack允许子组件堆叠&am…

什么是数据为先营销?为什么它对市场部如此重要?

数据为先营销希望能帮助各地的市场人员与高管们建立联系&#xff0c;实现这些商业目标&#xff0c;并真正学会如何适当地跟踪一切数据&#xff0c;这样他们就知道自己是否真的达到了收入目标&#xff0c;ROI&#xff0c;这些商业目标&#xff0c;而不是仅仅说我们是被数据驱动型…

先进的数字隔离技术提高了太阳能逆变器的可靠性

介绍 一个多世纪以来&#xff0c;化石燃料发电设施一直被证明是坚固可靠的能源&#xff0c;但这些久经考验的电力设施规模大、复杂&#xff0c;而且建造成本越来越高。以最小的碳足迹和环境影响清洁地操作它们也具有挑战性和成本高昂。相比之下&#xff0c;现代光伏&#xff0…

CSDN涨粉就这几招

目录说明涨粉不可不知的几件事几个常规的涨粉之道CSDN的数据运营之道粉丝列表关注列表关注某人取消关注获得某个用户的主要信息&#xff1a;昵称、排名、原创数、粉丝数等其它数据有了数据&#xff0c;怎么涨粉&#xff1f;说明 直到今年&#xff0c;我才开始重视涨粉&#xf…