OkHttp相关问题全解析,字节跳动Android面试凉凉经

本文深入解析OkHttp的Dispatcher组件,包括线程池管理、并发请求限制和队列机制。同时,讨论了OkHttp的拦截器体系,如RetryAndFollowUpInterceptor、BridgeInterceptor和CacheInterceptor,以及应用拦截器与网络拦截器的区别。还涉及HTTP缓存原理,如Expires、Cache-Control头以及强制缓存和协商缓存策略。
摘要由CSDN通过智能技术生成

transmitter.timeoutEnter()

transmitter.callStart()

try {

client.dispatcher.executed(this)//第1步

return getResponseWithInterceptorChain()//第2步

} finally {

client.dispatcher.finished(this)//第3步

}

}

把大象装冰箱,统共也只需要三步。

第一步

调用Dispatcher的execute方法,那Dispatcher是什么呢?从名字来看它是一个调度器,调度什么呢?就是所有网络请求,也就是RealCall对象。网络请求支持同步执行和异步执行,异步执行就需要线程池、并发阈值这些东西,如果超过阈值需要将超过的部分存储起来,这样一分析Dispatcher的功能就可以总结如下:

  • 记录同步任务、异步任务及等待执行的异步任务。
  • 线程池管理异步任务。
  • 发起/取消网络请求API:execute、enqueue、cancel。

OkHttp设置了默认的最大并发请求量 maxRequests = 64 和单个host支持的最大并发量 maxRequestsPerHost = 5。

同时用三个双端队列存储这些请求:

Dispatcher

//异步任务等待队列

private val readyAsyncCalls = ArrayDeque()

//异步任务队列

private val runningAsyncCalls = ArrayDeque()

//同步任务队列

private val runningSyncCalls = ArrayDeque()

为什么要使用双端队列?很简单因为网络请求执行顺序跟排队一样,讲究先来后到,新来的请求放队尾,执行请求从对头部取。

说到这LinkedList表示不服,我们知道LinkedList同样也实现了Deque接口,内部是用链表实现的双端队列,那为什么不用LinkedList呢?

实际上这与readyAsyncCalls向runningAsyncCalls转换有关,当执行完一个请求或调用enqueue方法入队新的请求时,会对readyAsyncCalls进行一次遍历,将那些符合条件的等待请求转移到runningAsyncCalls队列中并交给线程池执行。尽管二者都能完成这项任务,但是由于链表的数据结构致使元素离散的分布在内存的各个位置,CPU缓存无法带来太多的便利,另外在垃圾回收时,使用数组结构的效率要优于链表。

回到主题,上述的核心逻辑在promoteAndExecute方法中:

#Dispatcher

private fun promoteAndExecute(): Boolean {

val executableCalls = mutableListOf()

val isRunning: Boolean

synchronized(this) {

val i = readyAsyncCalls.iterator()

//遍历readyAsyncCalls

while (i.hasNext()) {

val asyncCall = i.next()

//阈值校验

if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.

if (asyncCall.callsPerHost().get() >= this.maxRequestsPerHost) continue // Host max capacity.

//符合条件 从readyAsyncCalls列表中删除

i.remove()

//per host 计数加1

asyncCall.callsPerHost().incrementAndGet()

executableCalls.add(asyncCall)

//移入runningAsyncCalls列表

runningAsyncCalls.add(asyncCall)

}

isRunning = runningCallsCount() > 0

}

for (i in 0 until executableCalls.size) {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值