总结自https://www.bilibili.com/video/BV1sT4y1P7mH
现在的HttpURLConnection底层实现也采用的是OkHttp。
HTTP协议是应用层协议,要HTTP通信先要建立TCP连接。使用一个连接池放入所有的tcp连接。不需要每次通信完成三次握手减少了请求延迟。
分发器Dispatcher,负责请求任务什么时候执行
http请求会经过什么步骤?
1、域名解析DNS--得到IP,
2、根据IP建立TCP连接(经过三次握手)---得到Socket对象。
3、利用Socket输出流写出Http报文。
拦截器就是负责完成上述过程的。+各种优化(连接池)
分发器Dispatcher
*利用OkhttpClient的Builder模式可以构建自己的Dispatcher
从call开始看
2.png 3.png得到RealCall后 调用同步/异步的执行方法执行
异步请求enqueue(Callback):
即调用call的异步请求
5.png回到enqueue(Callback):
先Synchronized(this){...},如果这个call被调用了则抛出异常,所以call只能调用一次。如果想多次调用要clone().
Call clone = call.clone();
clone.enqueue(new Callback(){...});
eventListener 里面可以监听dns解析开始、请求开示等过程
最后一句:
client.dispatcher().enqueue(new AsyncCall(responseCallback));
说明最终会调用到分发器的enqueue方法!传了一个AsyncCall(是一个Runnable)
进入分发器
先看异步的,三个问题:
1、call进来是如何判断放入等待队列还是运行队列的?
2、当call进入运行队列,应为是异步的、同时运行多个线程,需要一个线程池(ThreadPool)来管理,ready-》Running条件是什么
3、分发器里的线程池定义、维护
问题一回答:
正在执行的异步请求个数不大于默认64个
&&同一个域名请求最大数不大于默认5个
问题二回答:
每次执行完一个请求
calls.remove(call)方法移除请求完的call
promoteCalls()方法代码如下:
从ready获取一个方法放到running执行
问题三回答:
12.png里面是一个SynchoronousQueue<Runnable> queue类型的线程池,这个线程池特点是没有容量。每次来任务时走判断流程都会初始化一个线程,实现高并发无阻塞
13.png 14.png对同步请求 会加入runningSyncCalls,然后执行,只是一个记录的作用
拦截器
这一行执行拦截器
15.png 16.png采用责任链设计模式
17.pngU型的、逐个运行完后按顺序返回
18.png*OKHttp设置缓存后才会开启缓存。
网友评论