本平臺的文章更新會有延遲,你們能夠關注微信公衆號-顧林海,包括年末前會更新kotlin由淺入深系列教程,目前計劃在微信公衆號進行首發,若是你們想獲取最新教程,請關注微信公衆號,謝謝java
OkHttp發送的同步或異步請求隊列的狀態會在dispatcher中進行管理,dispatcher的做用就是用於維護同步和異步請求的狀態,內部維護一個線程池,用於執行相應的請求。web
在dispatcher內部維護着三個隊列,這三個隊列以下:微信
private final Deque<RealCall.AsyncCall> readyAsyncCalls = new ArrayDeque<>();
private final Deque<RealCall.AsyncCall> runningAsyncCalls = new ArrayDeque<>();
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
複製代碼
runningAsyncCalls表示的是正在執行的異步請求隊列。異步
readyAsyncCalls表示就緒狀態的異步請求隊列,若是當前的請求不知足某種條件時,當前的異步請求會進入就緒等待的異步請求隊列中,當知足某種條件時,會從就緒等待的異步請求隊列中取出異步請求,放入正在執行的異步請求隊列中。this
runningSyncCalls表示的正在執行的同步請求隊列。spa
除了上面的三個隊列,還有一個參數也是很是重要的,以下:線程
private @Nullable ExecutorService executorService;
複製代碼
executorService就是一個線程池對象,OkHttp的異步請求操做會放入這個線程池中。code
OkHttp的異步請求在dispatcher中的一系列操做能夠理解爲生產者消費者模式,其中Dispatcher是生產者,它是運行在主線程中的,ExecutorService表明消費者池。cdn
當同步和異步請求結束後,會調用dispatcher的finished方法,將當前的請求從隊列中移除。對象
client.dispatcher().finished(this);
複製代碼
這段代碼是在finally塊中,也就是說,不管請求成不成功,仍是出現異常,這段代碼都會執行,保證了請求的整個生命週期從開始到銷燬。
接下來,咱們從新看看同步請求和異步請求在dispatcher中的操做。
一、同步請求會執行dispatcher的executed方法:
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
複製代碼
在executed方法中,只是將當前請求RealCall存入正在執行的同步請求隊列中。
二、異步請求會執行dispatcher的enqueue方法;
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
synchronized void enqueue(RealCall.AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//第一步
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
//第二步
readyAsyncCalls.add(call);
}
}
複製代碼
上一節在講解異步請求時已經解釋過了,這裏直接複製過來:在enqueue方法前使用了synchronized關鍵字進行修飾,也就是爲這個方法加了個同步鎖,繼續往下看第一步,先是判斷當前異步請求總數是否小於設定的最大請求數(默認是64),以及正在運行的每一個主機請求數是否小於設定的主機最大請求數(默認是5),若是知足這兩個條件,就會把傳遞進來的AsyncCall對象添加到正在運行的異步請求隊列中,而後經過線程池執行這個請求。若是知足不了上面的兩個條件就會走第二步,將AsyncCall對象存入readyAsyncCalls隊列中,這個readyAsyncCalls就是用來存放等待請求的一個異步隊列。
其中線程池的建立和獲取代碼以下:
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;
}
複製代碼
建立線程池時,第一個參數表示核心線程數,設置爲0,當線程池空閒一段時間後,就會將線程池中的全部線程進行銷燬;第二個參數表示最大線程數,設置爲整型的最大值,具體多少線程數仍是受限OkHttp中的maxRequests這個參數;第三個參數表示當咱們的線程數大於核心線程數的時候,多餘的空閒線程存活的最大時間爲60秒,結合第一個核心線程數爲0,也就是說OkHttp中的線程在工做完畢後,會在60秒後進行關閉。
搜索微信「顧林海」公衆號,按期推送優質文章。