- final class AsyncCall extends NamedRunnable {}
所以Call本质就是一个Runable线程操作元肯定是放进excutorService中直接启动的。
2 线程池的复用和管理
2.1 图解
为了完成调度和复用,定义了两个队列分别用作等待队列和执行任务的队列。这两个队列都是Dispatcher 成员变量。Dispatcher是一个控制执行,控制所有Call的分发和任务的调度、通信、清理等操作。这里只介绍异步调度任务。
-
/** Ready async calls in the order they’ll be run. */
-
private final Deque readyAsyncCalls = new ArrayDeque<>();
-
/** Running asynchronous calls. Includes canceled calls that haven’t finished yet. */
-
private final Deque runningAsyncCalls = new ArrayDeque<>();
在《okhttp连接池复用机制》文章中我们在缓存Connection连接的时候也是使用的Deque双端队列。这里同样的方式,可以方便在队列头添加元素,移除尾部的元素。

2.2 过程分析
Call代用equeue方法的时候
-
synchronized void enqueue(AsyncCall call) {
-
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
-
runningAsyncCalls.add(call);
-
executorService().execute(call);
-
} else {
-
readyAsyncCalls.add(call);
-
}
-
}
方法中满足执行队列里面不足最大线程数maxRequests并且Call对应的host数目不超过maxRequestsPerHost 的时候直接把call对象直接推入到执行队列里,并启动线程任务(Call本质是一个Runnable)。否则,当前线程数过多,就把他推入到等待队列中
。Call执行完肯定需要在runningAsyncCalls 队列中移除这个线程。那么readyAsyncCalls队列中的线程在什么时候才会被执行呢。
追溯下AsyncCall 线程的执行方法
-
@Override
-
protected void execute() {
-
boolean signalledCallback = false;
-
try {
-
Response response = getResponseWithInterceptorChain(forWebSocket);
-
if (canceled) {
-
signalledCallback = true;
-
responseCallback.onFailure(RealCall.this, new IOException(“Canceled”));
-
} else {
-
signalledCallback = true;
-
responseCallback.onResponse(RealCall.this, response);
-
}
-
} catch (IOException e) {
-
if (signalledCallback) {
-
// Do not signal the callback twice!
-
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
-
} else {
-
responseCallback.onFailure(RealCall.this, e);
-
}
-
} finally {
-
client.dispatcher().finished(this);
-
}
-
}
-
}
这里做了核心request的动作,并把失败和回复数据的结果通过responseCallback 回调到Dispatcher。执行操作完毕了之后不管有无异常都会进入到dispactcher的finished方法。
-
private void finished(Deque calls, T call, boolean promoteCalls) {
-
int runningCallsCount;
-
Runnable idleCallback;
-
synchronized (this) {
-
if (!calls.remove(call)) throw new AssertionError(“Call wasn’t in-flight!”);
-
if (promoteCalls) promoteCalls();
-
runningCallsCount = runningCallsCount();
-
idleCallback = this.idleCallback;
-
}
-
&& idleCallback != null) {
-
idleCallback.run();
-
}
-
}
gCallsCount = runningCallsCount(); -
idleCallback = this.idleCallback;
-
}
-
&& idleCallback != null) {
-
idleCallback.run();
-
}
-
}










