美文网首页
Okhttp3 Dispatcher源码浅析(三)

Okhttp3 Dispatcher源码浅析(三)

作者: 徘徊0_ | 来源:发表于2020-05-08 10:11 被阅读0次
  • okhttp 同步/异步 请求都会在Dispatcher中管理其状态。
  • Dispatcher内部维护了一个线程池,用于执行请求call
  • Dispatcher维护请求的状态(维护任务队列)
一、Dispatcher 维护的队列
 /** 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<>();//运行状态的同步队列

异步请求,维护了两个队列readyAsyncCalls 和 runningAsyncCalls

二、Dispatcher 维护的线程池
/** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService;

线程池的创建:

public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
三、Dispatcher 关键方法分析

1,在执行异步请求的时候,会调用到Dispatcher.enqueue(AsyncCall call)方法

synchronized void enqueue(AsyncCall call) {
    //运行队列数量 < 最大数量  并且 host 也要小于最大数量
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);//在执行的时候,就直接将Call添加到运行队列中
      executorService().execute(call);//线程池,执行call
    } else {
      readyAsyncCalls.add(call);//如果不满足,就加入到准备(缓冲)队列中
    }
  }

2,异步or同步,执行到最后,都会调用Dispatcher.finished(Deque<T> calls, T call, boolean promoteCalls)方法;
异步 promoteCalls =true;
同步 promoteCalls =false;

private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      //先将该请求,从calls 中删除
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls(); //异步,会进入到该方法中
      runningCallsCount = runningCallsCount();//重新计算一下,运行的count
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }
//----------------------分割线--------------------------
public synchronized int runningCallsCount() {
    //该方法,就是获取正在执行call的总数量(异步+同步队列的size)
    return runningAsyncCalls.size() + runningSyncCalls.size();
  }


3,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();

      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();//条件满足,将call从准备队列中删除
        runningAsyncCalls.add(call);//将call 添加到 运行队列 中
        executorService().execute(call);//线程池执行
      }

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }

相关文章

网友评论

      本文标题:Okhttp3 Dispatcher源码浅析(三)

      本文链接:https://www.haomeiwen.com/subject/triarqtx.html