一张图讲懂分层时间轮流程

401 阅读2分钟

时间轮算法

TimerWheel实现 参考 Kafka Hutool Hierarchical Timing Wheels

时间轮 是一种 实现延迟功能(定时器) 的 巧妙算法。 如果一个系统存在大量的任务调度,时间轮可以高效的利用线程资源来进行批量化调度。 把大批量的调度任务全部都绑定时间轮上,通过时间轮进行所有任务的管理,触发以及运行。 能够高效地管理各种延时任务,周期任务,通知任务等。

TimeWheel.svg

延时任务对比

  • Timer、DelayQueue 和 ScheduledThreadPool,它们都是基于优先队列实现的,O(logn) 的时间复杂度
  • 时间轮的实现类似钟表的运作方式,分层时间轮在正常情况, 它的任务插入和删除时间复杂度都为O(1)

SystemTimer

准确来说 时间轮是数据结构

时间轮+DelayQueue=定时器

DelayQueue是心脏,是动力

TimeWheel 构成

  • tickMs(基本时间跨度):时间轮由多个时间格组成,每个时间格代表当前时间轮的基本时间跨度(tickMs)。
  • wheelSize(时间单位个数):时间轮的时间格个数是固定的,可用(wheelSize)来表示, 那么整个时间轮的总体时间跨度(interval)可以通过公式 tickMs × wheelSize计算得出。
  • currentTime(当前所处时间):时间轮还有一个表盘指针(currentTime),用来表示时间轮当前所处的时间, currentTime 是 tickMs 的整数倍。currentTime 可以将整个时间轮划分为到期部分和未到期部分, currentTime 当前指向的时间格也属于到期部分,表示刚好到期,需要处理此时间格所对应的 TimerTaskList 的所有任务。
  • overflowWheel (上级时间轮)
  • buckets 数组中的每个元素可以存放一个定时任务列表(TimerTaskList)。 TimerTaskList 是一个环形的双向链表,链表中的每一项表示的都是定时任务项(TimerTaskEntry),其中封装了真正的定时任务 TimerTask。

TimerWheel Add流程

TimeWheel.svg

  1. 首先在最小的TimerWheel执行Add
  2. 检查任务是否取消,是否已过期,若是,结束
  3. 检查此任务是不是在interval内,若大于interval,到当前TimerWheeloverflowWheel执行Add方法
  4. 如果是是在interval内,加入此TimerWheel。检查加入的桶(TimerTaskList)是不是新创建的,如果是加入DelayQueue
  5. 因为同一个TimerTaskList都是要同时处理的。

TimerWheel 推进时间流程

TimeWheel.svg

  1. DelayQueue中获取一个TimerTaskList
  2. 更新 TimerWheelcurrentTime
  3. 遍历TimerTaskList,每个元素TimerTask 在最小的TimerWheel执行Add 这一步是因为这个TimerTask是在原来的TimerWheel到期了,而不是要执行了
  4. 如果最小的TimerWheel执行Add返回false,说明真的要执行了,扔给线程池执行.