使用okhttp的第一步就是初始化了一个连接池,但是这个连接池是嵌套在Internal这个抽象类里面,为什么是使用抽象类,这个我需要思考一下。其中如何对线程池get和put,这个后续会分析到。
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
static {
Internal.instance = new Internal() {
@Override
public void addLenient(Headers.Builder builder, String line) {
builder.addLenient(line);
}
@Override
public void addLenient(Headers.Builder builder, String name, String value) {
builder.addLenient(name, value);
}
@Override
public void setCache(Builder builder, InternalCache internalCache) {
builder.setInternalCache(internalCache);
}
@Override
public boolean connectionBecameIdle(
ConnectionPool pool, RealConnection connection) {
return pool.connectionBecameIdle(connection);
}
@Override
public RealConnection get(ConnectionPool pool, Address address,
StreamAllocation streamAllocation, Route route) {
return pool.get(address, streamAllocation, route);
}
@Override
public boolean equalsNonHost(Address a, Address b) {
return a.equalsNonHost(b);
}
@Override
public Socket deduplicate(
ConnectionPool pool, Address address, StreamAllocation streamAllocation) {
return pool.deduplicate(address, streamAllocation);
}
@Override
public void put(ConnectionPool pool, RealConnection connection) {
pool.put(connection);
}
@Override
public RouteDatabase routeDatabase(ConnectionPool connectionPool) {
return connectionPool.routeDatabase;
}
@Override
public int code(Response.Builder responseBuilder) {
return responseBuilder.code;
}
@Override
public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket,
boolean isFallback) {
tlsConfiguration.apply(sslSocket, isFallback);
}
@Override
public HttpUrl getHttpUrlChecked(String url)
throws MalformedURLException, UnknownHostException {
return HttpUrl.getChecked(url);
}
@Override
public StreamAllocation streamAllocation(Call call) {
return ((RealCall) call).streamAllocation();
}
@Override
public Call newWebSocketCall(OkHttpClient client, Request originalRequest) {
return RealCall.newRealCall(client, originalRequest, true);
}
};
}
}
不管是异步请求也好还是同步请求都会通过dispatcher的线程池进行分发。
final class RealCall implements Call {
@Override
public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
// 发起请求
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//将一个requeset请求包装成一个realcall,放入一部请求中
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
final class AsyncCall extends NamedRunnable {
@Override
protected void execute() {
boolean signalledCallback = false;
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) {
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);
}
}
//进入责任链模式,开始经行网络请求
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) {
//针对websocket的网络连接器
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);
}
}
其中dispatcher的任务是当任务开始执行时将任务插入队列中,当任务结束时将任务remove掉。dispatcher有3个队列,同步/异步 队列,其中一个是ready队列。
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
/**
* 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<>();
public synchronized ExecutorService executorService() {
if (executorService == null) {
//核心线程数为0,则无需等待直接执行该线程。Integer.MAX_VALUE保证了线程的最大并发量
//60s为线程最大等待时间,SynchronousQueue不存储如何线程,如果有就立即执行。
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher",
false));
}
return executorService;
}
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
synchronized void enqueue(AsyncCall call) {
//todo : 1、如果正在执行的请求小于64
// 2、相同host的请求不能超过5个
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call); //正在执行的请求
executorService().execute(call); //线程池跑任务
} else {
//加入ready队列
readyAsyncCalls.add(call);
}
}
//异步请求
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
//同步请求
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
//promoteCalls判断是否为同步请求
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//在dispatcher列表中移除该请求
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();
}
}
/**
* 从ready获取任务放入异步队列执行
*/
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
// 同一Host请求只能同时有5个
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
}
总结:okhttpclient初始化连接池为后续的连接做准备,realcall控制request请求执行的详细流程,而dispatcher管理同步和异步队列,以及ready队列。保证当一个异步请求完成时及时清理。并添加新的请求进行处理。