1. 程式人生 > >Okhttp——佇列和執行緒池

Okhttp——佇列和執行緒池

這是很簡單的,但是假如面試官問你,你知道咋回答不?

對於同步:

開始的時候放到同步佇列,結束的時候從同步佇列中取出;

對於非同步:

開始的時候判斷非同步佇列元素數是否大於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的資料就髒了,但是還是會觸發回撥。看起來是錯了,不過這是一個無關緊要的方法,所以不做併發也可以。