Okhttp——佇列和執行緒池
阿新 • • 發佈:2018-12-14
這是很簡單的,但是假如面試官問你,你知道咋回答不?
對於同步:
開始的時候放到同步佇列,結束的時候從同步佇列中取出;
對於非同步:
開始的時候判斷非同步佇列元素數是否大於64?再遍歷一遍,看看和這個AsyncCall相同的host有沒有超過5個?
如果沒有,扔進非同步佇列;否則,扔進等待佇列。
在任務執行完畢後,會把等待佇列的任務取出來,重複上述判斷。
執行緒池就不用說了,同步是不用執行緒池的,後者用全部是非核心的執行緒池,因為IO、網路操作發起後就等待了,然後這段時間片為了充分利用只好開啟新的執行緒。
有個注意點還是挺有意思的
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) { int runningCallsCount; Runnable idleCallback; synchronized (this) { if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!"); if (promoteCalls) promoteCalls(); runningCallsCount = runningCallsCount(); idleCallback = this.idleCallback; } if (runningCallsCount == 0 && idleCallback != null) { idleCallback.run(); } }
這裡有一個idleCallback,這個東西用來通知:所有的請求都已經完成啦。其實也就是執行佇列為0的時候會通知下。
看到這裡我還有一個疑惑,就是if裡的內容放到sync內和sync外有什麼區別?
這很簡單。如果放到sync內,可以確保執行佇列為0的時候,回撥觸發,這沒問題;
如果放到sync外,可能同時有多個執行緒走到if,假如A執行緒先到,B執行緒後到,A執行緒走到if的時候count=0,然後B走到if的時候count假如等於1,這個時候A的資料就髒了,但是還是會觸發回撥。看起來是錯了,不過這是一個無關緊要的方法,所以不做併發也可以。