介绍
Dispatcher对应于应用层,通过Dispatcher实现线程的复用
源码分析
重点分析executorService()
,finished
,promoteCalls()
executorService()
//executorService是否为空,可以自定义线程池
if (executorService == null) {
//构建一个最少为0,最多无限制,空闲存活时间为60秒,
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
//无缓冲队列,线程工厂名为OkHttp Dispatcher
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
内置的executorService是一个无缓冲,先进先出的线程池,可以适应于一般的网络请求,如果是其他有一定要求的请求,比如列表图片加载(有优先级),可能就不太适用了。
finished
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();
}
}
通过finished方法来主动控制线程的调度。
promoteCalls
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相同的Request已满
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
//可能添加线程到满
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
扩展
Dispatcher向我们展示了怎样创建一个高并发,底阻塞,主动调度的线程池,想要了解更多的线程创建优化,建议阅读《Effectivie Java》并发章节