本篇文章已授權(quán)微信公眾號(hào)guolin_blog(郭霖)獨(dú)家發(fā)布
okhttp一經(jīng)推出,讓其他的網(wǎng)絡(luò)請(qǐng)求框架變得黯然失色。網(wǎng)上關(guān)于okhttp的介紹文章一大堆,這里我就不繼續(xù)bb了,今天我嘗試從源碼的角度去分析一下okhttp的一個(gè)工作流程。其實(shí)在動(dòng)筆寫這篇文章之前,我已經(jīng)在網(wǎng)上看過(guò)不少關(guān)于okhttp源碼分析的文章,怎么說(shuō)呢,有些文章,一上來(lái)就是一個(gè)大總結(jié)或者一個(gè)UML圖,讓人看得晦澀難懂。對(duì)于大部分沒(méi)有閱讀過(guò)okhttp源碼的人來(lái)說(shuō),全盤托出的一上來(lái)一大堆接口啊類啊什么的,容易把人整暈。今天我嘗試用通俗易懂的語(yǔ)言來(lái)描述一下同步、異步的操作流程,以及okhttp背后到底干了啥。
先貼一下 okhttp的github地址:okhttp項(xiàng)目地址。最新的源碼是3.0+,而3.0與舊版本多少還是有些差別的,這里我就不介紹了,感興趣的話自行去百度。
同步請(qǐng)求
// 構(gòu)建okHttpClient,相當(dāng)于請(qǐng)求的客戶端,Builder設(shè)計(jì)模式
OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
// 構(gòu)建一個(gè)請(qǐng)求體,同樣也是Builder設(shè)計(jì)模式
Request request = new Request.Builder().url("http://www.baidu.com").build();
// 生成一個(gè)Call對(duì)象,該對(duì)象是接口類型,后面會(huì)說(shuō)
Call call = okHttpClient.newCall(request);
try {
// 拿到Response
Response response = call.execute();
Log.i("TAG",response.body().string());
} catch (IOException e) {
}
以上就是一個(gè)簡(jiǎn)單的同步請(qǐng)求示例代碼,我們來(lái)看一看要經(jīng)過(guò)哪些步驟:
1.通過(guò)Builder模式創(chuàng)建OkHttpClient對(duì)象和Request對(duì)象
2.調(diào)用OkHttpClient的newCall方法,獲取一個(gè)Call對(duì)象,參數(shù)是Request
3.調(diào)用execute方法獲取一個(gè)Respone
(一) OkHttpClient源碼分析
public static final class Builder {
Dispatcher dispatcher;
...
...
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
}
public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
this.maxIdleConnections = maxIdleConnections;
this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration);
// Put a floor on the keep alive duration, otherwise cleanup will spin loop.
if (keepAliveDuration <= 0) {
throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration);
}
}
Builder是OkHttpClient一個(gè)靜態(tài)內(nèi)部類,在Builder的構(gòu)造函數(shù)中進(jìn)行了一系列的初始化操作,其中Dispatcher中文是分發(fā)器的意思,和攔截器不同的是分發(fā)器不做事件處理,只做事件流向。他負(fù)責(zé)將每一次Requst進(jìn)行分發(fā),壓棧到自己的線程池,并通過(guò)調(diào)用者自己不同的方式進(jìn)行異步和同步處理,那具體是怎么操作的呢?后面會(huì)講。ConnectionPool是一個(gè)連接池對(duì)象,它可以用來(lái)管理連接對(duì)象,從它的構(gòu)造方法中可以看到連接池的默認(rèn)空閑連接數(shù)為5個(gè),keepAlive時(shí)間為5分鐘。
(二) Request源碼分析
public static class Builder {
@Nullable HttpUrl url;
String method;
Headers.Builder headers;
@Nullable RequestBody body;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
}
Builder()構(gòu)造函數(shù)中設(shè)置了默認(rèn)的請(qǐng)求方法是GET方法,Request類的build()方法是用來(lái)創(chuàng)建一個(gè)Request對(duì)象,將當(dāng)前的Builder對(duì)象傳進(jìn)去,并完成了對(duì)象的賦值。我們來(lái)看一下Request的構(gòu)造函數(shù):
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tags = Util.immutableMap(builder.tags);
}
將Builder類的相關(guān)屬性賦值給Request的相關(guān)屬性,這也是Builder模式的精髓。
(三) Call對(duì)象的創(chuàng)建:newCall()執(zhí)行分析
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false);
}
可以看到newCall方法內(nèi)部調(diào)用了RealCall的newRealCall方法,Call是一個(gè)接口,RealCall是它的實(shí)現(xiàn)類,接下來(lái)我們?nèi)ewRealCall方法內(nèi)部看看
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
在newRealCall方法里,完成了RealCall對(duì)象的創(chuàng)建,并把它返回出去。至此,Call對(duì)象已經(jīng)創(chuàng)建完畢,實(shí)際上創(chuàng)建的對(duì)象是Call的實(shí)現(xiàn)類RealCall 對(duì)象。
(四) Response對(duì)象的創(chuàng)建: call.execute()執(zhí)行分析
前面已經(jīng)說(shuō)到 Call call = okHttpClient.newCall(request)拿到的是一個(gè)RealCall對(duì)象,所以我們直接去RealCall類的execute()方法看它的源碼
@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);
}
}
在同步代碼塊中,首先判斷excuted是不是true,它的含義是否有在執(zhí)行,如果是,拋出異常,如果沒(méi)有執(zhí)行過(guò),將excuted置為true。eventListener.callStart(this)開(kāi)啟事件監(jiān)聽(tīng),eventListener在RealCall對(duì)象創(chuàng)建的時(shí)候,也一起創(chuàng)建了。
接下來(lái)我們看看execute()的核心方法: client.dispatcher().executed(this)、 Response result = getResponseWithInterceptorChain()、client.dispatcher().finished(this)
public Dispatcher dispatcher() {
return dispatcher;
}
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
首先調(diào)用了Dispatcher的dispatcher()方法,dispatcher()方法返回一個(gè)Dispatcher對(duì)象,緊接著調(diào)用了Dispatcher的executed方法,往runningSyncCalls對(duì)象中添加了一個(gè) call對(duì)象,runningSyncCalls是一個(gè)存放同步請(qǐng)求的隊(duì)列,Dispatcher類中維護(hù)了3種類型的請(qǐng)求隊(duì)列:
/** 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<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
- readyAsyncCalls 是異步請(qǐng)求的就緒隊(duì)列
- runningAsyncCalls 是異步請(qǐng)求的執(zhí)行隊(duì)列
- runningSyncCalls 是同步請(qǐng)求的執(zhí)行隊(duì)列
調(diào)用完Dispatcher的execute()方法后,緊接著調(diào)用了getResponseWithInterceptorChain()方法。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
該方法返回一個(gè)Response對(duì)象,我們可以看到,在方法的第一行中就創(chuàng)建了interceptors 集合,然后緊接著放進(jìn)去很多攔截器對(duì)象,此處使用了責(zé)任鏈設(shè)計(jì)模式,依次在攔截器中做相應(yīng)的操作。
在Response的excute方法的finally模塊中,最后調(diào)用了 client.dispatcher().finished(this)。我們點(diǎn)進(jìn)去瞧一瞧
void finished(RealCall call) {
finished(runningSyncCalls, call);
}
finished方法內(nèi)部調(diào)用了它的重載的方法,并把同步請(qǐng)求的消息隊(duì)列對(duì)象和RealCall對(duì)象傳過(guò)去,我們繼續(xù)往下看。
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
在同步代碼快中,將call對(duì)象從同步請(qǐng)求消息隊(duì)列中移除,如果移除出問(wèn)題,就會(huì)拋出異常。 緊接著調(diào)用了promoteAndExecute方法:
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 (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
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;
}
同步代碼塊有一個(gè)for循環(huán),去迭代readyAsyncCalls,也就是待準(zhǔn)備消息隊(duì)列。但是我們從前面一步步分析過(guò)來(lái),并沒(méi)有往readyAsyncCalls添加過(guò)數(shù)據(jù),所以當(dāng)前的for循環(huán)并不會(huì)執(zhí)行,之后的一個(gè)for循環(huán)也不會(huì)執(zhí)行,isRunning返回false.
promoteAndExecute()方法返回false。
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
并且idleCallback 已經(jīng)完成了初始化,所以會(huì)執(zhí)行 idleCallback的run()方法
總結(jié):通過(guò)以上的分析,我們發(fā)現(xiàn)在同步請(qǐng)求中Dispatcher主要負(fù)責(zé)了兩件事,同步請(qǐng)求的保存和移除。
save.png


至此,okhttp3的同步請(qǐng)求源碼已經(jīng)分析完了,接下來(lái),我們看看okhttp3的異步請(qǐng)求源碼分析。
異步請(qǐng)求
// 構(gòu)建okHttpClient,相當(dāng)于請(qǐng)求的客戶端,Builder設(shè)計(jì)模式
OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
// 構(gòu)建一個(gè)請(qǐng)求體,同樣也是Builder設(shè)計(jì)模式
Request request = new Request.Builder().url("http://www.baidu.com").build();
// 生成一個(gè)Call對(duì)象,該對(duì)象是接口類型,后面會(huì)說(shuō)
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
簡(jiǎn)單的看下異步請(qǐng)求的幾個(gè)步驟:
1.通過(guò)Builder模式創(chuàng)建OkHttpClient對(duì)象和Request對(duì)象
2.調(diào)用OkHttpClient的newCall方法,獲取一個(gè)Call對(duì)象,參數(shù)是Request
3.調(diào)用call對(duì)象的enqueue()方法
步驟1和步驟2跟同步請(qǐng)求的步驟一致,主要看一下步驟3
異步請(qǐng)求源碼:call.enqueue() 源碼分析
異步請(qǐng)求和同步請(qǐng)求的步驟1和步驟2一致,都是在做準(zhǔn)備工作,并沒(méi)有發(fā)起請(qǐng)求,所以這次我們直接忽略了步驟1和步驟2的分析,直接分析步驟3的源碼,我們點(diǎn)開(kāi)RealCall的enqueue方法:
@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));
}
我們看看它的核心代碼: client.dispatcher().enqueue(new AsyncCall(responseCallback)),
client.dispatcher()返回一個(gè)Dispatcher對(duì)象沒(méi)什么可講的,緊接著調(diào)用Dispatcher的enqueue方法,參數(shù)是AsyncCall對(duì)象,我們先看看AsyncCall是什么?
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private volatile AtomicInteger callsPerHost = new AtomicInteger(0);
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
AtomicInteger callsPerHost() {
return callsPerHost;
}
}
只截取了部分代碼,該類繼承自NamedRunnable,我們看看NamedRunnable:
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
NamedRunnable 實(shí)現(xiàn)了Runnable 接口。
我們直接去Dispatcher的enqueue()看看做了哪些操作。
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();
}
在同步代碼塊中,將當(dāng)前的call請(qǐng)求添加到待準(zhǔn)備消息隊(duì)列中去,注意這里跟同步請(qǐng)求的區(qū)別,同步請(qǐng)求的時(shí)候,并沒(méi)有把當(dāng)前的call添加到準(zhǔn)備消息隊(duì)列中去。然后又調(diào)用了 promoteAndExecute()方法,同步請(qǐng)求的時(shí)候也調(diào)用了promoteAndExecute()方法
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 (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
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;
}
此時(shí),readyAsyncCalls不為空了,我們單獨(dú)的把這個(gè)for循環(huán)拎出來(lái)講:
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
這段代碼的含義是:把符合條件的call請(qǐng)求從readyAsyncCalls提升為runningAsyncCalls,我們看這段代碼中的兩個(gè)if語(yǔ)句,第一個(gè)if語(yǔ)句判斷當(dāng)前異步請(qǐng)求的執(zhí)行隊(duì)列長(zhǎng)度大于等于請(qǐng)求最大值,如果滿足直接跳出for循環(huán),maxRequests的值為64,第二個(gè)if語(yǔ)句判斷當(dāng)前執(zhí)行的異步請(qǐng)求隊(duì)列中相同主機(jī)的請(qǐng)求數(shù)是否大于等于maxRequestsPerHost(每個(gè)主機(jī)最大請(qǐng)求數(shù),默認(rèn)為5),如果這兩個(gè)條件都不滿足的情況下,把從readyAsyncCalls取出來(lái)的call請(qǐng)求,存到臨時(shí)的
executableCalls 隊(duì)列中去。
緊接著去遍歷executableCalls:
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
從executableCalls獲取AsyncCall對(duì)象,并且調(diào)用它的executeOn方法,executeOn()方法參數(shù)是executorService(),我們看看executorService():
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
可以看出,該方法是一個(gè)同步方法,返回的是一個(gè)線程池對(duì)象,ThreadPoolExecutor()的第二個(gè)參數(shù)傳入了Integer的最大值,即線程池所能容納的最大線程數(shù)為Integer.MAX_VALUE,雖然這里設(shè)置了很大的值,但是實(shí)際情況下并非會(huì)達(dá)到最大值,因?yàn)樯厦鎒nqueue()方法中有做了判斷。
回到 asyncCall.executeOn(executorService())這里,executorService返回了一個(gè)線程池對(duì)象,緊接著調(diào)用線程池對(duì)象的execute方法,execute()方法傳入實(shí)現(xiàn)了Runable接口的AsyncCall對(duì)象,前面在分析同步請(qǐng)求的時(shí)候,說(shuō)了AsyncCall實(shí)現(xiàn)了Runable接口

ok,現(xiàn)在我們要看看線程池做了什么操作,直接去NamedRunnable的run方法看看做了什么操作。
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
execute()是一個(gè)抽象方法,所以我們直接去NamedRunnable的實(shí)現(xiàn)類AsyncCall的execute()方法看:
@Override protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
e = timeoutExit(e);
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
這段代碼才是真正執(zhí)行異步請(qǐng)求的邏輯,getResponseWithInterceptorChain()返回Response對(duì)象,然后判斷retryAndFollowUpInterceptor是否取消回調(diào)CallBack接口的onFailure()或onResponse()方法,最后finally中,和同步請(qǐng)求的處理一樣,調(diào)用了Dispatcher對(duì)象的finished()方法。
void finished(RealCall call) {
finished(runningSyncCalls, call);
}
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
看完promoteAndExecute()方法的具體操作,我們發(fā)現(xiàn),調(diào)用eneque的時(shí)候會(huì)把call請(qǐng)求添加到readyAsyncCalls(異步請(qǐng)求準(zhǔn)備隊(duì)列)中,而readyAsyncCalls隊(duì)列中的請(qǐng)求什么時(shí)候執(zhí)行呢,看完promoteAndExecute的代碼就恍然大悟了。
總結(jié):異步請(qǐng)求中,我們先去遍歷異步請(qǐng)求的就緒隊(duì)列,并判斷異步請(qǐng)求的執(zhí)行隊(duì)列的隊(duì)列大小是否小于設(shè)置的最大數(shù)的時(shí)候,如果條件滿足,把該請(qǐng)求添加到異步請(qǐng)求的執(zhí)行隊(duì)列中去,同時(shí)把該請(qǐng)求添加到臨時(shí)的異步請(qǐng)求的執(zhí)行隊(duì)列去中。之后,遍歷這個(gè)臨時(shí)的異步請(qǐng)求的執(zhí)行隊(duì)列,去執(zhí)行AsyncCall的execute()方法。
