时间轮类似于钟表,上面有时分秒的刻度,秒针一秒一秒的跳,对应到秒级任务,如果刻度跨度为毫秒则可以实现毫秒调度 。每一个刻度后面都连接着当前秒应该执行的任务,系统每次都调度当前时间指针下的任务 。其数据结构就可以看成「数组+链表」的实现,时间轮是一种算法思想,在各开发语言中没有对应的实现,HashMap、Dict 也可以满足要求 。XXL-JOB 就是使用的 ConcurrentHashMap<Integer,List<Integer>> 。时间轮相比于 DelayQueue 怎么样呢,又存在哪些问题,该怎么解决呢?
时间轮靠时间指针调度,不存在任务排序,每次都是取出当前刻度下的任务 。每次都是O(1),假如当前时刻下有多个任务,当前队列需要全部弹出 。
与 DelayQueue 不同,时间轮每个刻度下都是一个独立的队列,各队列的存取互不影响,可以通过线程安全的队列来实现,所以存取的并发性能比 DelayQueue 高很多 。
时间轮的本质是随着时间的推移,不断的轮询当前时间刻度下的任务,与 DelayQueue 不同,即使时间轮为空时,依然轮询,会产生空轮询 。在 XXL-JOB 里就存在这种问题,幸好一般情况下,都是秒级调度,空轮询也没有大影响 。但如果是毫秒级调度,空轮询是会影响系统性能的,比如 epoll CPU100% 的bug 和 Netty 空轮询bug 。
需要保证在一个时间刻度下,一个任务不能出现两次,不然可能会多次调度 。
理想中的时间轮是能够满足以上 4 点要求,revolver 通过跳跃表数组实现基本结构ConcurrentSkipListSet<Integer>[],ConcurrentSkipListSet 是一个基于跳跃表实现的无锁的线程安全的、有序列、去重的列表表,向列表put元素并排序的时间复杂度是O(logN),ReentrantLock + condition + AtomicInteger 计数器避免空轮询 。
当任务数=0 时,调用 condition.await() take 被阻塞,当元素个数从无变成有的时候,调用 condition.signal(),也是一个典型的生产者消费者模型 。

文章插图

文章插图
某资料上就用这种设计做出了监控10亿级定时任务检测系统,时间轮是一种设计方式,非特定的数据结构,除了性能好之外其扩展性也是非常好的 。

文章插图
欢迎关注公众号:看起来很美(kanqilaihenmei_)
-- 完 --
推荐阅读
-
5G手机最核心的基带芯片,全球仅7大厂商掌握,中国占了四家
-
大建侃球@瓦妮莎曼巴日追思丈夫和女儿:生活实在太不公平,四年前科比退役
-
-
-
电池|内行人忠爱的两款大电池手机,最大6000mAh,最小5100mAh!
-
入坑索尼A6100,或许是最好的入门级APS-C相机
-
-
文玩|那些暴涨又暴跌的文玩,骗走多少文玩人的血汗钱
-
流年絮语|张艺凡穿无袖衣体操服,当她抬起胳膊时,看清腋窝,不敢相信眼睛
-
-
秋声带雨荷被病毒干倒无人问津,后悔为美国卖命了?曾为美国出生入死的老兵
-
-
招聘|现在的烟草局算什么性质的单位,还有编制吗?怎样算正式工?
-
电视剧|《欢乐合唱团》演员湖上失踪,剩4岁儿子在船上,她是该剧组第5个出事儿的人
-
澎湃影像|阿塞拜疆总统称正继续在纳卡地区进行军事活动
-
JOJO杂谈01,快用你无敌的白金之星想想办法,空条承太郎
-
华为首发5nm麒麟9000,华为暗示:Mate 40即将发布
-
北晚新视觉网特朗普:如果我们不做检测,病例就会变少,美国确诊病例超141万
-
经济|原创外资大举买入中国资产,中国资产为啥成了被抢购的香饽饽?
-
你不可不知的,中国56个民族,除了汉族之外,它才是最大的民族