第一次寫博客,說是博客卑笨,其實就是自己的學(xué)習(xí)筆記茧泪,希望能堅持下去!
OKHttp的簡單請求示例:
OkHttpClient.Builder builder =new OkHttpClient.Builder();
OkHttpClient client = builder.build();
Request request =new Request.Builder()
.url("")
.build();
try {
// 同步請求
client.newCall(request).execute();
// 異步請求
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response)throws IOException {
}
});
} catch (IOException e) {
e.printStackTrace();
}
以下是自己做的請求順序?qū)D:
請求順序
結(jié)合圖總結(jié)一下異步請求過程
- 如果滿足異步執(zhí)行條件圆恤,則入隊并立即執(zhí)行突倍,否則,加入ready隊列哑了,等待合適的條件去將其取出赘方;當(dāng)一個請求執(zhí)行結(jié)束,會調(diào)用Dispatcher的promoteCalls方法弱左,會將ready隊列中的AsyncCall取出窄陡,入隊并開始執(zhí)行,然后在線程池中調(diào)用所執(zhí)行的Call的getResponseWithInterceptorChain()拆火,獲取到請求結(jié)果跳夭,并回調(diào)出去。
- 同步異步的執(zhí)行區(qū)別:都是調(diào)用的getResponseWithInterceptorChain()方法们镜,異步線程是通過線程池來執(zhí)行的币叹,而同步則是直接執(zhí)行
Dispatcher類
1. 線程池
該類中,獲取線程池的方法為executorService()
模狭,該方法內(nèi)部實現(xiàn)的是懶加載的無邊界限制的線程池颈抚。
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
可見,OKHttp中使用的線程池是ThreadPoolExecutor
參數(shù)說明:
- 0:核心線程數(shù)量嚼鹉,0表示后臺線程空閑后不會保留贩汉,經(jīng)過一段時間后停止
- Integer.MAX_VALUE:線程池可容納的最大線程數(shù)量
- TimeUnit.SECOND:線程池中的線程數(shù)量大于核心線程數(shù)量時驱富,空閑線程等待60s即被終止,若小于匹舞,則立即終止
- new SynchronousQueue<Runnable>():線程等待隊列
- 最后一個參數(shù):線程工廠
這里褐鸥,需要對SynchronousQueue進(jìn)行說明:
該隊列的特點(diǎn)是:每插入一個元素必須等待另一個元素的移除,每移除一個元素都會等待另一個元素的插入赐稽,也就是說叫榕,該隊列內(nèi)部其實沒有元素,容量為0姊舵;這樣設(shè)計的意義就是可以快速的傳遞元素晰绎,很適合高頻率的請求處理。
2. 結(jié)束請求finished方法
- 先移除該call對象
- 根據(jù)傳入的promoteCalls參數(shù)蠢莺,確定是否調(diào)用promoteCalls()方法寒匙;若為同步請求,則該參數(shù)為false躏将,若為異步請求锄弱,則參數(shù)為true,需要執(zhí)行下一步的入隊操作
3. promoteCalls()方法
該方法是操作隊列祸憋,控制請求執(zhí)行的關(guān)鍵会宪,負(fù)責(zé)將ready隊列的call轉(zhuǎn)化為running狀態(tài)
- 首先,它會判斷當(dāng)前執(zhí)行的request是否大于64
- 若小于蚯窥,則遍歷ready隊列掸鹅,取出call并將其添加進(jìn)running隊列,調(diào)用線程池的execute(call)方法
- 遍歷的終止條件:ready隊列為空拦赠,或者running滿足最大數(shù)量限制
回調(diào)該方法有三個時機(jī): - 一個請求執(zhí)行結(jié)束巍沙,finished方法中
- Dispatcher的setMaxRequestsPerHost()被調(diào)用
- Dispatcher的setMaxRequests()被調(diào)用
總結(jié)
該類控制著異步請求時的任務(wù)調(diào)度和線程池,并未直接負(fù)責(zé)請求的執(zhí)行荷鼠,配合線程池句携,實現(xiàn)了高并發(fā),低阻塞的運(yùn)行允乐。
參考:這位大佬的博客