时间轮算法HashedWheelTimer
创始人
2024-03-29 11:28:15
0

文章目录

    • 一.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

io.nettynetty-all4.1.45.Final

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);//等待定时任务执行完毕后,将时间轮内部工作线程停止,这里只是粗略的等待,也可以使用CountDownLatchThread.sleep(10000);timer.stop();

2.取消某个定时任务

       //构建时间轮对象HashedWheelTimer timer = new HashedWheelTimer(1, TimeUnit.SECONDS, 10);//添加定时任务1Timeout 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,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...