时间轮算法

前言

现实开发中有许多的延迟操作,比如定时清理过期数据等,在JDK中自带的Timer或者DelayQueue来实现延迟的功能,但很多开源的中间件中并没有使用Timer或者DelayQueue来实现而是使用基于时间轮算法来实现执行延迟任务功能,例如2.7.0以上的Dubbo基于时间轮实现了,失败定时重发,心跳检测等延迟操作。JDK的Timer和DelayQueue插入和删除操作的平均时间复杂度为O(nlog(n))并不能满足的高性能插入删除的要求,而而基于时间轮可以将插入和删除操作的时间复杂度都降为O(1) 。

实现

时间轮是参考钟表盘来实现,钟表盘上的表针会在固定时间后向前走一格,走完12格后又回到原来位置重复上面流程,时间轮也类似定义了几个格,在固定时间在这几个格上走动。盗图看下结构

如上图,时间轮有多个时间格组成,每个时间格里放置了任务队列,当走到某个时间格时会执行当前时间格里的任务。时间轮的每个时间格用slot表示,时间轮的时间格长度是固定的用wheelLength表示,每个时间格走动的间隔时间也是固定的用tickDuration表示,假设当前指向时间格的第一个位置,要执行一个延迟时间为deadline的任务,那么需要先找到对应的slot将任务加入才能顺利执行,其对应的计算公式:slot = (deadline / tickDuration)%wheelLength;走完一圈时间轮所需的时间为:loopDuration = tickDuration*wheelLength,如果任务的deadline > loopDuration,那么第一轮走到对应的slot是不能执行此任务,需要计算执行此任务需要经过轮数,计算格式为:remainingRounds = deadline / tickDuration / wheelLength;也就是说次任务需要再经过remainingRounds+1轮并走到对应的slot才能执行。

举个例子:

定义时间格长度wheelLength=12,每个时间格间隔时间tickDuration=1s,假设当前指向时间格的第一个位置,如果执行一个需要20s后执行的延迟任务,根据公式slot=8,remainingRound=1,也就是说时间轮走2圈,并且走到时间格位置为8的地方才能执行任务。

转载于:https://my.oschina.net/u/945573/blog/3099796

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值