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

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

OkHttp 的請求實際上由 RealCall 對象發(fā)起另伍,RealCall 提供了 execute 函數(shù)發(fā)起同步請求和 enqueue 函數(shù)發(fā)起異步請求

同步請求的執(zhí)行

  1. 首先會判斷當前這個 RealCall 對象是否已經(jīng)在執(zhí)行斤斧,如果是的話會拋出異常
  2. 交給 Dispatch 做統(tǒng)計
  3. 執(zhí)行 OkHttp 的各個責任鏈發(fā)起真正的請求功能
  4. 等待責任鏈返回結(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ā)起異步請求

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

  1. 判斷當前任務是否執(zhí)行洪唐,如果已經(jīng)在執(zhí)行拋出一個異常
  2. 構(gòu)建一個 AsyncCall 對象交給 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 類中針對異步任務維護了兩個隊列尺锚,一個 readyAsyncCalls (等待執(zhí)行隊列),一個正在執(zhí)行的任務隊列 runningAsyncCalls

  1. 將該任務交給等待執(zhí)行隊列
  2. 調(diào)用 promoteAndExecute 執(zhí)行請求
  /** 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í)行的隊列
  2. 輪訓所有的等待執(zhí)行隊列讶凉,取出任務
  3. 當前正在執(zhí)行的隊列是否達到 64 的上限
  4. 是否同時發(fā)起了 5 個請求
  5. 如果滿足要求染乌,將消息加入可執(zhí)行隊列,和正在執(zhí)行隊列
  6. 從可執(zhí)行隊列中取出消息懂讯,通過線程池執(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 中通過線程池發(fā)起的

  1. 發(fā)起任務執(zhí)行
  2. 當 finish 時移除任務
    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!
        }
      }
    }
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荷憋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子褐望,更是在濱河造成了極大的恐慌台谊,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件譬挚,死亡現(xiàn)場離奇詭異锅铅,居然都是意外死亡,警方通過查閱死者的電腦和手機减宣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門盐须,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人漆腌,你說我怎么就攤上這事贼邓。” “怎么了闷尿?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵塑径,是天一觀的道長。 經(jīng)常有香客問我填具,道長统舀,這世上最難降的妖魔是什么匆骗? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮誉简,結(jié)果婚禮上碉就,老公的妹妹穿的比我還像新娘。我一直安慰自己闷串,他們只是感情好瓮钥,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烹吵,像睡著了一般碉熄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肋拔,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天具被,我揣著相機與錄音,去河邊找鬼只损。 笑死一姿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的跃惫。 我是一名探鬼主播叮叹,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼爆存!你這毒婦竟也來了蛉顽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤先较,失蹤者是張志新(化名)和其女友劉穎携冤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闲勺,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡曾棕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了菜循。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翘地。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖癌幕,靈堂內(nèi)的尸體忽然破棺而出衙耕,到底是詐尸還是另有隱情,我是刑警寧澤勺远,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布橙喘,位于F島的核電站,受9級特大地震影響胶逢,放射性物質(zhì)發(fā)生泄漏厅瞎。R本人自食惡果不足惜饰潜,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望磁奖。 院中可真熱鬧囊拜,春花似錦某筐、人聲如沸比搭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽身诺。三九已至,卻和暖如春抄囚,著一層夾襖步出監(jiān)牢的瞬間霉赡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工幔托, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穴亏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓重挑,卻偏偏與公主長得像嗓化,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谬哀,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349

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

  • 從三月份找實習到現(xiàn)在刺覆,面了一些公司,掛了不少史煎,但最終還是拿到小米谦屑、百度、阿里篇梭、京東氢橙、新浪、CVTE恬偷、樂視家的研發(fā)崗...
    時芥藍閱讀 42,214評論 11 349
  • 本文出自 Eddy Wiki 充蓝,轉(zhuǎn)載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 2,076評論 0 14
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,806評論 25 707
  • Java8張圖 11、字符串不變性 12喉磁、equals()方法谓苟、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,696評論 0 11
  • 第三章 Java內(nèi)存模型 3.1 Java內(nèi)存模型的基礎 通信在共享內(nèi)存的模型里协怒,通過寫-讀內(nèi)存中的公共狀態(tài)進行隱...
    澤毛閱讀 4,347評論 2 22