Okhttp3源碼分析之四

看過OKHTTP源碼的都會知道,裏面有個任務調度Dispatcher

這裏分析一下Dispatcher源碼:

public final class Dispatcher {
  private int maxRequests = 64;//最大請求數
  private int maxRequestsPerHost = 5;//最大主機數
  private @Nullable Runnable idleCallback;//空閒回調

  private @Nullable ExecutorService executorService;//線程池

  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//等待執行隊列

  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在執行隊列(異步)

  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在執行隊列(同步)


  //創建線程池
  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

    ***省略代碼

  //入隊
  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);
    }
    promoteAndExecute();
  }

 //取消所有請求
 public synchronized void cancelAll() {
    for (AsyncCall call : readyAsyncCalls) {
      call.get().cancel();
    }

    for (AsyncCall call : runningAsyncCalls) {
      call.get().cancel();
    }

    for (RealCall call : runningSyncCalls) {
      call.cancel();
    }
  }

//啓動並執行
 private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      //遍歷異步隊列
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();

        //判斷是否超過最大值
        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.

        i.remove();
        executableCalls.add(asyncCall);
        runningAsyncCalls.add(asyncCall);
      }
      isRunning = runningCallsCount() > 0;
    }

    //遍歷可執行隊列,並執行
    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());
    }

    return isRunning;
  }

   //加入同步隊列
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

   //當前線程結束時,執行空閒回調
  private <T> void finished(Deque<T> calls, T call) {
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      idleCallback = this.idleCallback;
    }

    boolean isRunning = promoteAndExecute();

    if (!isRunning && idleCallback != null) {
      idleCallback.run();
    }
  }

  ***省略代碼
}

代碼中可以看出,Dispatcher利用三個隊列來維持線程池的調度

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章