內部維護隊列與線程池,完成請求的調配。markdown
問題一:請求發送到哪裏去?架構
Dispatcher是保存同步和異步Call的地方,並負責執行異步AsyncCall。併發
異步請求流程:框架
- 異步請求 Call (RealCall)—>enqueue()
- RealCall 的enqueue()
- dispatcher 的enqueue():將請求添加到等待執行的異步請求隊列中
- 不斷從readyAsyncCalls中取出要執行的請求放到runningAsyncCalls中,並將readyAsyncCalls中的移除,若是其中的runningAsynCalls不滿,且call佔用的host小於最大數量,則將call加入到runningAsyncCalls中執行
getResponseWithInterceptorChain();
複製代碼
問題二:如何從ready移動到running?異步
每次任務結束後,都會在ready中讀取一個任務放進running中。socket
每一個請求執行完成就會從running移除,同時進行第一步相同邏輯的判斷,決定是否移動。this
client.dispatcher().finished(this);
複製代碼
問題三:分發器的線程池是怎麼定義的?spa
無等待,最大併發。SynchronousQueue : 無容量的隊列。線程
緣由:因爲請求數量較大,請求的生命週期較短,會致使頻繁的建立和銷燬請求,同時也會頻繁的建立和銷燬該請求對應的線程,有可能會形成內存抖動等問題,因此使用了線程池。設計
我的理解:由於在請求發送時,分發器已經維護兩個隊列,這兩個隊列框架能夠自身進行維護,若是發到線程池裏還有一個隊列的話,就表明着會有三個隊列,在線程池還要再次等待,會致使效率低下
完成整個請求過程
Http請求的過程:DNS解析-->創建Tcp/Ip鏈接-->使用socket對象的輸出流寫出http的報文