面试官:你给我说一下什么是时间轮吧? (中)

简介: 面试官:你给我说一下什么是时间轮吧? (中)

不要误以为下标对应的链表中的圈数必须按照从小到大的顺序来,这个是没有必要的。

好,现在又来一个 403 秒后需要执行的任务,应该挂在哪儿?

403 mod 8 = 3,那么就是这样的:


image.png

我为什么要不厌其烦的给你说怎么计算,怎么挂到对应的下标中去呢?

因为我还需要引出一个东西:待分配任务的队列。

上面画 800 秒、 400 秒和 403 秒的任务的时候,我还省略了一步。

其实应该是这样的:

image.png

任务并不是实时挂到时间轮上去的,而是先放到一个待分配的队列中,等到特定的时间再把待分配队列中的任务挂到时间轮上去。

具体是什么时候呢?

下面讲源码的时候再说。

其实除了待分配队列外,还有一个任务取消的队列。

因为放入到时间轮的任务是可以被取消的。

比如在 Dubbo 里面,检验调用是否超时也用的是时间轮机制。

假设一个调用的超时时间是 5s,5s 之后需要触发任务,抛出超时异常。

但是如果请求在 2s 的时候就收到了响应,没有超时,那么这个任务是需要被取消的。

对应的源码就是这块,看不明白没关系,看一眼就行了,我只是为了证明我没有骗你:

org.apache.dubbo.remoting.exchange.support.DefaultFuture#received


image.png

原理画图出来大概就是这样,然后我还差一张图。

把源码里面的字段的名称给你对应到上面的图中去。

主要把这几个对象给你对应上,后面看源码就不会太吃力了:

image.png

对应起来是这样的:

image.png

注意左上角的“worker的工作范围”把整个时间轮包裹了起来,后面看源码的时候你会发现其实整个时间轮的核心逻辑里面没有线程安全的问题,因为 worker 这个单线程把所有的活都干完了。

最后,再提一嘴:比如在前面 FailbackClusterInvoker 的场景下,时间轮触发了重试的任务,但是还是失败了,怎么办呢?

很简单,再次把任务放进去就行了,所以你看源码里面,有一个叫做 rePut 的方法,干的就是这事:

org.apache.dubbo.rpc.cluster.support.FailbackClusterInvoker.RetryTimerTask#run


image.png

这里的含义就是如果重试出现异常,且没有超过指定重试次数,那么就可以再次把任务仍回到时间轮里面。

等等,我这里知道“重试次数”之后,还能干什么事儿呢?

比如如果你对接过微信支付,它的回调通知有这样的一个时间间隔:

image.png

我知道当前重试的次数,那么我就可以在第 5 次重试的时候把时间设置为 10 分钟,扔到时间轮里面去。

时间轮就可以实现上面的需求。

当然了,MQ 的延迟队列也可以,但是不是本文的讨论范围。

但是用时间轮来做上面这个需求还有一个问题:那就是任务在内存中,如果服务挂了就没有了,这是一个需要注意的地方。

除了 FailbackClusterInvoker 外,其实我觉得时间轮更合适的地方是做心跳。

这可太合适了, Dubbo 的心跳就是用的时间轮来做。

org.apache.dubbo.remoting.exchange.support.header.HeartbeatTimerTask#doTask

微信图片_20220428214509.png


从上图可以看到,doTask 方法就是发送心跳包,每次发送完成之后调用 reput 方法,然后再次把发送心跳包的任务仍回给时间轮。

好了,不再扩展应用场景了。

接下来,进入源码分析,跟上节奏,不要乱,大家都能学。

开卷!

image.png



目录
相关文章
|
7月前
|
算法 前端开发 JavaScript
【面试题】 面试官:你都工作3年了,这个算法题都不会?
【面试题】 面试官:你都工作3年了,这个算法题都不会?
|
5月前
|
存储 安全 Java
面试官没想到一个ArrayList,我都能跟他扯半小时
面试官:List集合都知道哪些对象?作为四大集合之一的List,在业务开发中我们比较常见的是以下 3 种:ArrayList、Vector、LinkedList,业务开发我们接触最多就是容器类库了,容器类库可以说是面向对象语言最重要的类库。大家看看在工作里你比较熟悉的是哪个?这篇文章南哥打算专注于List集合,后面四大集合之Map、Queue、Set后续再来填坑,比心心♥。
136 2
面试官没想到一个ArrayList,我都能跟他扯半小时
|
4月前
|
消息中间件 Java 中间件
复盘女朋友面试4个月的并发面试题
该文章主要复盘了关于并发的面试题,包括线程池的使用场景、原理、参数合理化设置,以及ThreadLocal、volatile、synchronized关键字的使用场景和原理,还介绍了juc并发工具包中aqs的原理,强调在面试中要将自己理解的点与面试官讲透。
复盘女朋友面试4个月的并发面试题
|
7月前
|
监控 安全 Java
【面试题】面试必备我跟面试官聊了一个小时线程池!
【面试题】面试必备我跟面试官聊了一个小时线程池!
448 1
|
Python
我这样回答多线程并发,面试官非要跟我做朋友!
我这样回答多线程并发,面试官非要跟我做朋友!
124 0
|
7月前
|
Java 调度
金三银四面试必问:线程有几种状态
金三银四面试必问:线程有几种状态
37 0
|
Cloud Native 程序员 Go
程序员面试中的懒惰:如何避免成为失败的原因
程序员面试中的懒惰:如何避免成为失败的原因
36 0
|
Dubbo Java 应用服务中间件
面试官:你给我说一下什么是时间轮吧? (上)
面试官:你给我说一下什么是时间轮吧? (上)
286 0
面试官:你给我说一下什么是时间轮吧? (上)
|
Dubbo Java 应用服务中间件
面试官:你给我说一下什么是时间轮吧? (下)
面试官:你给我说一下什么是时间轮吧? (下)
192 0
面试官:你给我说一下什么是时间轮吧? (下)
|
Java 程序员
面试被问AQS、ReentrantLock答不出来?这些知识点让我和面试官聊了半小时!
Java并发编程的核心在于java.concurrent.util包,juc中大多数同步器的实现都围绕了一个公共的行为,比如等待队列、条件队列、独占获取、共享获取等,这个行为的抽象就是基于AbstractQueuedSynchronized(AQS)。AQS定义了多线程访问共享资源的同步器框架。