OkHttp3源碼學習(一)

參考:http://www.lxweimin.com/p/6637369d02e7

1. 線程池基礎

1.1. 線程池好處

初學Android時異步都用new Thread+Handler,但是java還有個利器,線程池。比如Picasso、Rxjava等框架使用的都是線程池。

線程池的關鍵在于線程復用以減少非核心任務的損耗。主要原因在于減少了創建線程、銷毀線程的時間。

1.2. OkHttp中的線程池

首先,OkHttp擁有2種運行方式,一種是同步阻塞調用并直接返回的形式,另一種是通過內部線程池分發調度實現非阻塞的異步回調。這兩講的是第二種方式。

OkHttp配置的的線程池在Dispatcher類里:

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;
}

new了一個核心線程(或最小保留線程)為0、最大線程數為Integer.MAX_VALUE、空閑線程存活時間為60s的線程池。但是Dispatcher默認同時支持最多64個并發請求,單個IP最多5個請求(可以設定)。

1.3. OkHttp任務調度

在OkHttp的異步請求時,一般進行如下構造

OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder()
      .url("http://qq.com").get().build();
client.newCall(request).enqueue(new Callback() {
     @Override
     public void onFailure(Call call, IOException e) { }
     @Override
     public void onResponse(Call call, Response response) throws IOException { }
}
);

但是最終enqueue執行的是Dispatcher的入隊操作:

synchronized void enqueue(AsyncCall call) {
  if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      //添加正在運行的請求
      runningAsyncCalls.add(call);
      //線程池執行請求
      executorService().execute(call);
 } else {
      //添加到緩存隊列排隊等待
      readyAsyncCalls.add(call);
 }
}

這里的maxRequests 就是默認最大并發64,maxRequestsPerHost則為每個ip最大并發數。

1.4. AsyncCall

從上面的代碼可以看到Dispatcher的enqueue方法中需要的是AsyncCall。參考原文可以知道finally中執行了這行代碼:

client.dispatcher().finished(this);

這行代碼有兩個作用,1、完成本次執行的任務。2、調用下個任務的執行。這是OkHttp一個很出彩的地方,就是在try/finally中調用了finished函數,可以主動控制等待隊列的移動,而不是采用鎖,極大減少了編碼復雜性。

------總結-----

1、在多線程任務調度中可以用類似反向代理(如似于Nginx)與線程池配合實現了高并發,低阻塞的運行
2、在AsyncCall 中采用try/finally中調用了finished函數,主動控制等待隊列的移動,而不是采用鎖
3、采用Deque作為緩存,按照入隊的順序先進先出

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容