内部维护队列与线程池,完成请求的调配。markdown
问题一:请求发送到哪里去?架构
Dispatcher是保存同步和异步Call的地方,并负责执行异步AsyncCall。并发
异步请求流程:框架
- 异步请求 Call (RealCall)—>enqueue()
- RealCall 的enqueue()
- dispatcher 的enqueue():将请求添加到等待执行的异步请求队列中
- 不断从readyAsyncCalls中取出要执行的请求放到runningAsyncCalls中,并将readyAsyncCalls中的移除,若是其中的runningAsynCalls不满,且call占用的host小于最大数量,则将call加入到runningAsyncCalls中执行
getResponseWithInterceptorChain();
复制代码
问题二:如何从ready移动到running?异步
每次任务结束后,都会在ready中读取一个任务放进running中。socket
每一个请求执行完成就会从running移除,同时进行第一步相同逻辑的判断,决定是否移动。this
client.dispatcher().finished(this);
复制代码
问题三:分发器的线程池是怎么定义的?spa
无等待,最大并发。SynchronousQueue : 无容量的队列。线程
缘由:因为请求数量较大,请求的生命周期较短,会致使频繁的建立和销毁请求,同时也会频繁的建立和销毁该请求对应的线程,有可能会形成内存抖动等问题,因此使用了线程池。设计
我的理解:由于在请求发送时,分发器已经维护两个队列,这两个队列框架能够自身进行维护,若是发到线程池里还有一个队列的话,就表明着会有三个队列,在线程池还要再次等待,会致使效率低下
完成整个请求过程
Http请求的过程:DNS解析-->创建Tcp/Ip链接-->使用socket对象的输出流写出http的报文