Dispatcher做的事很简单
默认包含一个corePollSize为0的线程池,闲置一段时间后所有线程都会销毁
还有三个队列,等待请求的队列、异步请求中的队列、同步请求中的队列
设置并发数量限制,不断把readyAsyncCalls中请求往runningAsyncCalls中添加,所有请求结束时回调idleCallback
public final class Dispatcher {
private int maxRequests = 64;//最大并发请求数
private int maxRequestsPerHost = 5;//正在请求的队列(runningAsyncCalls)中,相同host的请求的最大数量
Runnable idleCallback;//Dispatcher闲置回调函数
private @Nullable ExecutorService executorService;
/**
* Ready async calls in the order they'll be run.
* 将要请求的异步请求队列
*/
private final Deque<RealCall.AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/**
* Running asynchronous calls. Includes canceled calls that haven't finished yet.
* 正在请求的异步请求队列,包含已经取消但是还没有结束的请求
*/
private final Deque<RealCall.AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/**
* Running synchronous calls. Includes canceled calls that haven't finished yet.
* 正在请求的同步请求队列,包含已经取消但是还没有结束的请求
*/
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(
//corePoolSize:最小并发线程数,这里并发同时包括空闲与活动的线程,如果是0的话,空闲一段时间后所有线程将全部被销毁。
0,
//maximumPoolSize:最大线程数,当任务进来时可以扩充的线程最大值,当大于了这个值就会根据丢弃处理机制来处理
Integer.MAX_VALUE,
//keepAliveTime:当线程数大于corePoolSize时,多余的空闲线程的最大存活时间,类似于HTTP中的Keep-alive
60,
//TimeUnit unit:时间单位,一般用秒
TimeUnit.SECONDS,
//工作队列
new SynchronousQueue<Runnable>(),
//ThreadFactory threadFactory:单个线程的工厂,可以打Log,设置Daemon(即当JVM退出时,线程自动结束)等
Util.threadFactory("OkHttp Dispatcher", false)
);
}
return executorService;
}
/**
* 设置最大并发线程数,超过这个数量的请求要等runningAsyncCalls中的请求执行完成
* Set the maximum number of requests to execute concurrently. Above this requests queue in
* memory, waiting for the running calls to complete.
* <p>If more than {@code maxRequests} requests are in flight when this is invoked, those requests
* will remain in flight.
*/
public synchronized void setMaxRequests(int maxRequests) {
if (maxRequests < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequests);
}
this.maxRequests = maxRequests;
//从readyAsyncCalls中取出请求,放入runningAsyncCalls,直到达到最大请求数限制
promoteCalls();
}
public synchronized int getMaxRequests() {
return maxRequests;
}
/**
* 设置每个host请求的最大并发线程数,根据url的host来限制请求
* 请注意,对单个IP地址的并发请求可能仍然超出此限制:多个主机名可能共享IP地址或通过相同的HTTP代理进行路由。
* 如果超过{@code maxRequestsPerHost}请求在被调用时处于运行状态,那么这些请求将保持在运行状态。
* Set the maximum number of requests for each host to execute concurrently. This limits requests
* by the URL's host name. Note that concurrent requests to a single IP address may still exceed
* this limit: multiple hostnames may share an IP address or be routed through the same HTTP
* proxy.
* <p>If more than {@code maxRequestsPerHost} requests are in flight when this is invoked, those
* requests will remain in flight.
*/
public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) {
if (maxRequestsPerHost < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost);
}
this.maxRequestsPerHost = maxRequestsPerHost;
//从readyAsyncCalls中取出请求,放入runningAsyncCalls,直到达到最大请求数限制
promoteCalls();
}
public synchronized int getMaxRequestsPerHost() {
return maxRequestsPerHost;
}
/**
* 设置闲置回调函数,当dispatcher闲置时的回调函数(running calls返回数量为0时回调)
* 请求闲置的时间根据执行的是同步请求还是异步请求有差异
* 异步请求在onResponse或onFailure回调后才闲置,同步请求一旦执行execute()就闲置。
* Set a callback to be invoked each time the dispatcher becomes idle (when the number of running
* calls returns to zero).
* <p>Note: The time at which a {@linkplain Call call} is considered idle is different depending
* on whether it was run {@linkplain Call#enqueue(Callback) asynchronously} or
* {@linkplain Call#execute() synchronously}. Asynchronous calls become idle after the
* {@link Callback#onResponse onResponse} or {@link Callback#onFailure onFailure} callback has
* returned. Synchronous calls become idle once {@link Call#execute() execute()} returns. This
* means that if you are doing synchronous calls the network layer will not truly be idle until
* every returned {@link Response} has been closed.
*/
public synchronized void setIdleCallback(@Nullable Runnable idleCallback) {
this.idleCallback = idleCallback;
}
synchronized void enqueue(RealCall.AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//请求添加到runningAsyncCalls中,并用线程池执行请求
runningAsyncCalls.add(call);
executorService().execute(call);
} else {//runningAsyncCalls中并发请求达到上限,或者runningAsyncCalls中与call的host相同的请求达到上限,则把请求添加到readyAsyncCalls
readyAsyncCalls.add(call);
}
}
/**
* 取消所有请求,包括同步请求、异步请求、等待中的请求、执行中的请求
* call.get().cancel()实际上调用的是retryAndFollowUpInterceptor.cancel() -> StreamAllocation.cancel() -> closeQuietly(rawSocket);
*/
public synchronized void cancelAll() {
for (RealCall.AsyncCall call : readyAsyncCalls) {
call.get().cancel();
}
for (RealCall.AsyncCall call : runningAsyncCalls) {
call.get().cancel();
}
for (RealCall call : runningSyncCalls) {
call.cancel();
}
}
//从readyAsyncCalls中取出请求,往runningAsyncCalls中塞
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) {
return; // Already running max capacity.
}
if (readyAsyncCalls.isEmpty()) {
return; // No ready calls to promote.
}
//遍历等待请求的队列readyAsyncCalls
for (Iterator<RealCall.AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
RealCall.AsyncCall call = i.next();//readyAsyncCalls的请求
//runningAsyncCalls中与call的host相同的请求数量,小于同一host并发的最大数量限制时
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();//把该call从readyAsyncCalls中移除,添加到runningAsyncCalls中
runningAsyncCalls.add(call);
executorService().execute(call);//然后让线程池执行请求
}
//当runningAsyncCalls达到最大并发请求数时,打断循环,不再往runningAsyncCalls添加
if (runningAsyncCalls.size() >= maxRequests) {
return; // Reached max capacity.
}
}
}
/**
* 返回正在请求的异步队列中host与call的host相同的数量
* Returns the number of running calls that share a host with {@code call}.
*/
private int runningCallsForHost(RealCall.AsyncCall call) {
int result = 0;
for (RealCall.AsyncCall c : runningAsyncCalls) {
if (c.host().equals(call.host())) {
result++;
}
}
return result;
}
/**
* okHttpClient.newCall(request).execute()内部调用的就是这个dispatcher.execute(call)
* 把请求添加到队列中
*/
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(RealCall.AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
/** Used by {@code Call#execute} to signal completion. */
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
/**
* 每执行完一个请求,会调用该方法把已执行的请求从队列中移除
*/
private <T> void finished(Deque<T> 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;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();//触发闲置回调
}
}
/** Returns a snapshot of the calls currently awaiting execution. */
public synchronized List<Call> queuedCalls() {
List<Call> result = new ArrayList<>();
for (RealCall.AsyncCall asyncCall : readyAsyncCalls) {
result.add(asyncCall.get());
}
return Collections.unmodifiableList(result);
}
/** Returns a snapshot of the calls currently being executed. */
public synchronized List<Call> runningCalls() {
List<Call> result = new ArrayList<>();
result.addAll(runningSyncCalls);
for (RealCall.AsyncCall asyncCall : runningAsyncCalls) {
result.add(asyncCall.get());
}
return Collections.unmodifiableList(result);
}
public synchronized int queuedCallsCount() {
return readyAsyncCalls.size();
}
public synchronized int runningCallsCount() {
return runningAsyncCalls.size() + runningSyncCalls.size();
}
}
在实际请求中的调用:okHttpClient.newCall(request).execute();
@Override
public Response execute() throws IOException {
synchronized (this) {
if (executed) {
throw new IllegalStateException("Already Executed");
}
executed = true;
}
captureCallStackTrace();
try {
//由此可见execute方法真正执行的是dispatcher.execute(call);
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) {
throw new IOException("Canceled");
}
return result;
} finally {
//执行完成之后调用dispatcher.finished(call)把该已执行完的请求从队列中移除
client.dispatcher().finished(this);
}
}
注意一个小点:cancelAll()执行路径:
1、call.get().cancel() -> retryAndFollowUpInterceptor.cancel() -> StreamAllocation.cancel() -> closeQuietly(rawSocket)
取消任务,实际上是关闭socket。
2、socket的关闭不影响连接池的复用,每次连接时都会创建socket的(http1.1),http2.0对相同host的请求可以共用一个socket
RealConnection.connect() -> connectSocket() {
...
rawSocket = proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.HTTP
? address.socketFactory().createSocket()//创建的socket
: new Socket(proxy);//使用代理创建socket
...
//打开socket连接
Platform.get().connectSocket(rawSocket, route.socketAddress(), connectTimeout);
...//处理输入输出流(Okio)
} -> establishProtocol() - >connectTls() {
...
socket = sslSocket
...
}