OkHttp架构解析

OkHttp架构解析

Dispatcher分发器

内部维护队列与线程池,完成请求的调配。markdown

问题一:请求发送到哪里去?架构

Dispatcher是保存同步和异步Call的地方,并负责执行异步AsyncCall。并发

  • 针对同步请求,Dispatcher使用了一个Deque保存了同步任务;
  • 针对异步请求,Dispatcher使用了两个队列Deque,一个保存准备执行的请求(readyAsyncCalls),一个保存正在执行的请求(runningAsyncCalls)
  • 为何要用两个呢?由于Dispatcher默认支持最大的并发请求是64个,单个Host最多执行5个并发请求,若是超过,则Call会先被放入到readyAsyncCall中,当出现空闲的线程时,再将readyAsyncCall中的线程移入到runningAsynCalls中,执行请求。

异步请求流程:框架

  1. 异步请求 Call (RealCall)—>enqueue()
  2. RealCall 的enqueue()
  3. dispatcher 的enqueue():将请求添加到等待执行的异步请求队列中
  4. 不断从readyAsyncCalls中取出要执行的请求放到runningAsyncCalls中,并将readyAsyncCalls中的移除,若是其中的runningAsynCalls不满,且call占用的host小于最大数量,则将call加入到runningAsyncCalls中执行
getResponseWithInterceptorChain();
复制代码

问题二:如何从ready移动到running?异步

每次任务结束后,都会在ready中读取一个任务放进running中。socket

每一个请求执行完成就会从running移除,同时进行第一步相同逻辑的判断,决定是否移动。this

client.dispatcher().finished(this);
复制代码

问题三:分发器的线程池是怎么定义的?spa

无等待,最大并发。SynchronousQueue : 无容量的队列。线程

  • 为何使用线程池?

缘由:因为请求数量较大,请求的生命周期较短,会致使频繁的建立和销毁请求,同时也会频繁的建立和销毁该请求对应的线程,有可能会形成内存抖动等问题,因此使用了线程池。设计

  • 为何这么设计线程池?

我的理解:由于在请求发送时,分发器已经维护两个队列,这两个队列框架能够自身进行维护,若是发到线程池里还有一个队列的话,就表明着会有三个队列,在线程池还要再次等待,会致使效率低下

Interceptor拦截器

完成整个请求过程

Http请求的过程:DNS解析-->创建Tcp/Ip链接-->使用socket对象的输出流写出http的报文

相关文章
相关标签/搜索