先总体看一下okhttp请求的流程示意图:
- Dispatcher okhttp将请求(同步或者异步)一并放入Dispatcher分发器中,同步请求采用同步单线程的方式,函数使用excute,异步请求采用并发队列的分发与回调,函数使用enqueue
- dispatcher之后okhttp请求的一系列过程采用责任链的设计模式,一个功能一个功能用chain连在一起,责任链的先后顺序如下:
- RetryAndFollowUpInterceptor : 创建StreamAllocation对象,处理http的重定向,出错重试。对后续Interceptor的执行的影响:修改request及StreamAllocation。
- BridgeInterceptor:补全缺失的一些http header,Cookie设置。对后续Interceptor的执行的影响:修改request。
- CacheInterceptor:处理http缓存。对后续Interceptor的执行的影响:若缓存中有所需请求的响应,则后续Interceptor不再执行。
- ConnectInterceptor:借助于前面分配的StreamAllocation对象建立与服务器之间的连接(具体建立是在newStream方法中),并选定交互所用的协议是HTTP 1.1还是HTTP 2。对后续Interceptor的执行的影响:创建了httpStream和connection。
- CallServerInterceptor:处理IO,与服务器进行数据交换。对后续Interceptor的执行的影响:为Interceptor链中的最后一个Interceptor,没有后续Interceptor。
3.OkHttp里面的线程池ExecutorService,最小并发线程数为0,最大线程数为Integer.MAX_VALUE,当线程数大于corePoolSize
时,多余的空闲线程的最大存活时间为60秒,这里面所有的线程一旦空闲下来最长存活60秒;
可以看出,在Okhttp中,构建了一个阀值为[0, Integer.MAX_VALUE]的线程池,它不保留任何最小线程数,随时创建更多的线程数,当线程空闲时只能活60秒,它使用了一个不存储元素的阻塞工作队列,一个叫做"OkHttp Dispatcher"的线程工厂。
SynchronousQueue其实是一个阻塞队列,通俗理解就是队列数据被删除一个,队列就往内部新增一条数据,否则就保持阻塞状态。
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));