OkHttp同步請(qǐng)求和異步請(qǐng)求的區(qū)別

如何發(fā)起同步和異步請(qǐng)求

OkHttp 的請(qǐng)求實(shí)際上由 RealCall 對(duì)象發(fā)起,RealCall 提供了 execute 函數(shù)發(fā)起同步請(qǐng)求和 enqueue 函數(shù)發(fā)起異步請(qǐng)求

同步請(qǐng)求的執(zhí)行

  1. 首先會(huì)判斷當(dāng)前這個(gè) RealCall 對(duì)象是否已經(jīng)在執(zhí)行,如果是的話會(huì)拋出異常
  2. 交給 Dispatch 做統(tǒng)計(jì)
  3. 執(zhí)行 OkHttp 的各個(gè)責(zé)任鏈發(fā)起真正的請(qǐng)求功能
  4. 等待責(zé)任鏈返回結(jié)果
 @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    timeout.enter();
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      e = timeoutExit(e);
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

發(fā)起異步請(qǐng)求

OkHttp 的異步請(qǐng)求包裝成了 AsyncCall 對(duì)象,它是一個(gè)線程對(duì)象,作為內(nèi)部類聲明在 RealCall 中,由 Dispatch 類統(tǒng)計(jì)和執(zhí)行

  1. 判斷當(dāng)前任務(wù)是否執(zhí)行,如果已經(jīng)在執(zhí)行拋出一個(gè)異常
  2. 構(gòu)建一個(gè) AsyncCall 對(duì)象交給 Dispatch 類管理
@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

Dispatcher 類中針對(duì)異步任務(wù)維護(hù)了兩個(gè)隊(duì)列,一個(gè) readyAsyncCalls (等待執(zhí)行隊(duì)列),一個(gè)正在執(zhí)行的任務(wù)隊(duì)列 runningAsyncCalls

  1. 將該任務(wù)交給等待執(zhí)行隊(duì)列
  2. 調(diào)用 promoteAndExecute 執(zhí)行請(qǐng)求
  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
  
  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);
    }
    promoteAndExecute();
  }

promoteAndExecute

  1. 準(zhǔn)備一個(gè)可執(zhí)行的隊(duì)列
  2. 輪訓(xùn)所有的等待執(zhí)行隊(duì)列,取出任務(wù)
  3. 當(dāng)前正在執(zhí)行的隊(duì)列是否達(dá)到 64 的上限
  4. 是否同時(shí)發(fā)起了 5 個(gè)請(qǐng)求
  5. 如果滿足要求,將消息加入可執(zhí)行隊(duì)列,和正在執(zhí)行隊(duì)列
  6. 從可執(zhí)行隊(duì)列中取出消息,通過(guò)線程池執(zhí)行
  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;
  }

消息的執(zhí)行是由 RealCall 中通過(guò)線程池發(fā)起的

  1. 發(fā)起任務(wù)執(zhí)行
  2. 當(dāng) finish 時(shí)移除任務(wù)
    void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        executorService.execute(this);
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        eventListener.callFailed(RealCall.this, ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容