One of the core Okhttp study notes (b): Dispatcher

Learning materials:

BAT Daniel with your depth analysis of the top ten Android open-source framework

Previous article:
Okhttp study notes (a) an initial understanding && Source Analysis

Dispatcher class analysis

  • Synchronous, asynchronous request sent by the status management Dispatcher
  • Action: maintaining state synchronization and asynchronous requests, maintains a thread pool to execute the request

Member variables

  // 最大请求数
  private int maxRequests = 64;
  // 相同主机最大请求数
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;

  // 重要 维护的线程池
  private @Nullable ExecutorService executorService;
  
  // 准备状态中的异步请求队列
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  // 执行中的异步请求队列(包含已经取消但是还没取消的请求)
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  // 同步请求队列
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

Creating a Thread Pool

The core thread pool is set to 0, the maximum number of threads to the maximum Integer, but in fact is limited maxRequests, and automatically recovered in the 60s idle thread;

 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 of the executed method

Directly into the queue

synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

Dispatcher method of enqueue

 synchronized void enqueue(AsyncCall call) {
     // 判断请求数是佛满足要求
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
    // 加入运行队列并且使用线程池执行
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
    // 加入就绪队列
      readyAsyncCalls.add(call);
    }
  }

In what is called?

Asynchronous request, for example , in actual use, we are through newCall OkHttpClient's () method call enqueue method in Okhttp study notes (a) mentioned, is enqueue method RealCall class of actual implementation

  // realCall类里调用的dispatcher对象的 enqueue 方法
  client.dispatcher().enqueue(new AsyncCall(responseCallback)); 

AsyncCall is a Runnable Callback wraps is RealCall as an internal class, will ultimately execute the implementation of the thread pool method AsyncCall obtained result of the request by the execution request getResponseWithInterceptorChain () method, and the callback corresponding results, and will be held by RealCall client client object, the final call is finished method Dispatcher

 final class AsyncCall extends NamedRunnable {

    ...
    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
      // 获取拦截器链 获取response
        Response response = getResponseWithInterceptorChain();
        // 判断是否取消
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          // 取消则回调onFailure
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          // 没取消则回调onResponse
          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 {
          // 捕获到异常 回调到onFailure方法
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        // 调用finished方法
        client.dispatcher().finished(this);
      }
    }
    ...
 }

Dispatcher's finished method

After the final callbacks will come through the following methods:

  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;
    }
     // 执行数为0时,且idleCallback 不为空,执行idleCallback.run();
    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

In addition to removal request, focused look at promoteCalls asynchronous method will perform:

 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();
        runningAsyncCalls.add(call);
        executorService().execute(call); // 最终会执行AsyncCall的execute方法,见上面
      }

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

to sum up:

  1. Dispatcher is a scheduler created automatically created OkHttpClient;
  2. The default maximum number of requests is 64;
  3. The default maximum number of requests for the same host 5;
  4. Synchronization request: (in the RealCall) before call request dispatcher request queue is added, and then directly obtain a result;
  5. Asynchronous request: In the method RealCall enqueue calls the dispatcher, is determined in the dispatcher's methods enqueue added or join request queue waiting queue , AsyncCall final execution of the execute method, and the result acquisition request for a callback
  6. The request is complete: Dispatcher calls the finished method, the removal request, adjust the number of requests, if it is an asynchronous request, then will call promoteCalls method to invoke the next request
  7. Asynchronous request completes: promoteCalls method determines whether two conditions are satisfied (the same as the maximum number of requests and the number of hosts), if so, will be a call request queue press
Published 27 original articles · won praise 6 · views 1653

Guess you like

Origin blog.csdn.net/weixin_41802023/article/details/102859848