Android技术知识

OkHttp3源码学习之Dispatcher

2017-05-30  本文已影响0人  辰静暮夕

介绍

Dispatcher对应于应用层,通过Dispatcher实现线程的复用

源码分析

Dispatcher源码架构

重点分析executorService()finishedpromoteCalls()

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》并发章节

上一篇下一篇

猜你喜欢

热点阅读