Android源碼分析OkHttp5線程調度

NO IMAGE

同步任務線程調度

同步任務線程調度比較簡單

  • client.dispatcher.executed(this)同步執行,將任務放置到runningSyncCalls隊列
  • getResponseWithInterceptorChain開始執行任務
  • client.dispatcher.finished(this)執行結束
try {
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}

finished方法中有個idleCallback,不太明白其功能。

最後順便調用了一下promoteAndExecute()方法,個人理解為查詢是否存在異步任務,如果有,那就再處理一下吧。

異步任務線程調度

觸發

入口位於realcall的異步調用方法enqueue,首先將RealCall包裝為實現Runnable的AsyncCall

override fun enqueue(responseCallback: Callback) {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
transmitter.callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))
}

Dispatcher

然後到Dispatcher中enqueue方法, 將call添加到readyAsyncCalls隊列中

internal fun enqueue(call: AsyncCall) {
synchronized(this) {
readyAsyncCalls.add(call)
}
promoteAndExecute()
}

然後遍歷readyAsyncCalls將可以執行的任務轉移到runningAsyncCalls隊列,然後在線程池executorService中執行

private fun promoteAndExecute(): Boolean {
assert(!Thread.holdsLock(this))
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
synchronized(this) {
val i = readyAsyncCalls.iterator()
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.
i.remove()
asyncCall.callsPerHost().incrementAndGet()
executableCalls.add(asyncCall)
runningAsyncCalls.add(asyncCall)
}
isRunning = runningCallsCount() > 0
}
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)
}
return isRunning
}

線程池

接下來看executorService線程池,語法有點陌生,理解起來就是一個Client會創建一個Dispather, 進而都會初始化一個線程池ThreadPoolExecutor

private var executorServiceOrNull: ExecutorService? = null
@get:Synchronized
@get:JvmName("executorService") val executorService: ExecutorService
get() {
if (executorServiceOrNull == null) {
executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
SynchronousQueue(), threadFactory("OkHttp Dispatcher", false))
}
return executorServiceOrNull!!
}

執行

異步線程AsyncCall將在這個線程池裡執行,call的執行調用run方法,執行內容在前一章節已經描述

相關文章

Kubernetes多租戶集群實踐

SpringBoot連接多RabbitMQ源

[譯]如何準備你的GitHub,給面試官留個好印象

十幾道含答案的大廠面試題總結