参考代码 hzlulu/TimingWheel
TimerTask
时间轮中任务类的抽象类。实现Runnable接口。
成员变量包括:
- delayMs:超时的绝对时间
- TimerTaskEntry:存放在时间轮中时,与之相关联的包装类,用于定时达到之前,取消任务。
TimerTaskEntry
时间格中存放的列表中的具体节点类,也是任务的包装类。实现了Comparable接口,根据每个Entry的expirationMs过期时间进行比较。
成员变量包括:
- TimerTaskList:节点属于的时间格list
- TimerTaskEntry next:指向下一个Entry
- TimerTaskEntry pre:指向上一个Entry
- TimerTask:包装的任务对象
- expirationMs:到期时间
TimerTaskList
每个时间格表示的TimeTask列表,每个列表具有一个到期时间,当列表到期后,再将列表中的元素从新散布到时间格中。再散布的过程中会发现已经到期的任务,立即执行。
实现Delayed接口,提供getDelay方法返回给定单位的到期时间。
成员变量包括:
- AtomicInteger taskCounter:列表中任务的个数
- TimerTaskEntry root:列表的入口节点
- AtomicLong expiration:列表的到期时间。这个时间根据tickMs粗化后的到期时间。例如,当tickMs为1ms时,到期时间就是任务的到期时间;当tickMs为2s时,两个相差1s的任务放在同一个时间格内时,设置list的到期时间是相同的。
TimingWheel
时间轮类。定义了整个时间轮的基本属性。
成员变量包括:
- tickMs:时间格的单位
- wheelSize:时间格的个数
- interval:tickMs X wheelSize当前层时间轮的时间跨度
- taskCounter:整个时间轮的任务数量
- queue:时间格(TimerTaskList)按照到期时间组成的延时队列(在SystemTimer类的advanceClock中用来获取下一个时间格)
- currentTime:时间轮的初始化时间
- overflowWheel:高层时间轮
- TimerTaskList[] buckets:时间格数组
SystemTimer
整个时间轮的包装和调用类。通过add方法向时间轮中添加任务。通过advanceClock方法驱动时间轮。
整个时间轮流程
初始化
SystemTimer systemTimer = new SystemTimer("name");
添加任务
- systemTimer.add(new DelayedOperation(100))
- 包装为TimerTaskEntry
- 向TimingWheel中添加
- 如果添加失败,则判断任务是否已经取消或者已经到期
- 如果任务到期则立即执行,taskExecutor.submit()
添加到时间轮的逻辑
- 判断任务是否已经取消
- 判断任务是否已经到期
- 如果到期时间在当前层时间轮的范围内,在计算对应的bucket天机
- 如果超出当前层的时间范围,则递归想高层时间轮继续添加
驱动时间轮
- systemTimer.advanceClock()
- 从当前层时间轮的延时队列中获取到期的TimeTaskList
- 修改时间轮的当前时间
- 将TimeTaskList中的任务继续添加到时间轮当中,此时会用到上一步修改的当前时间,来判断任务是否过期
- 对于过期任务直接执行,否则继续添加到时间轮中
- 继续从延时队列中获取到期的bucket,直到获取完。