如何發(fā)起同步和異步請求
OkHttp 的請求實際上由 RealCall 對象發(fā)起另伍,RealCall 提供了 execute 函數(shù)發(fā)起同步請求和 enqueue 函數(shù)發(fā)起異步請求
同步請求的執(zhí)行
- 首先會判斷當前這個 RealCall 對象是否已經(jīng)在執(zhí)行斤斧,如果是的話會拋出異常
- 交給 Dispatch 做統(tǒng)計
- 執(zhí)行 OkHttp 的各個責任鏈發(fā)起真正的請求功能
- 等待責任鏈返回結(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í)行
- 判斷當前任務是否執(zhí)行洪唐,如果已經(jīng)在執(zhí)行拋出一個異常
- 構(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
- 將該任務交給等待執(zhí)行隊列
- 調(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
- 準備一個可執(zhí)行的隊列
- 輪訓所有的等待執(zhí)行隊列讶凉,取出任務
- 當前正在執(zhí)行的隊列是否達到 64 的上限
- 是否同時發(fā)起了 5 個請求
- 如果滿足要求染乌,將消息加入可執(zhí)行隊列,和正在執(zhí)行隊列
- 從可執(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ā)起的
- 發(fā)起任務執(zhí)行
- 當 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!
}
}
}