Android - 剖析OKHttp(2)- 调度请求

2020-11-05  本文已影响0人  杨0612

https://juejin.cn/post/7095315542202351623
这篇文章分析了,Request如何构建以及加入调度队列的。

源码分析基于 3.14.4

发起请求

//RealCall类中
@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }    
    client.dispatcher().enqueue(new AsyncCall(responseCallback));//1
  }

//Dispatcher类中
void enqueue(AsyncCall call) {
  synchronized (this) {
    readyAsyncCalls.add(call);//2
    // the same host.
    if (!call.get().forWebSocket) {
      AsyncCall existingCall = findExistingCallWithHost(call.host());//3
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
    }
  }
  promoteAndExecute();//4
}
private boolean promoteAndExecute() {
 
  List<AsyncCall> executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall asyncCall = i.next();

      if (runningAsyncCalls.size() >= maxRequests) break; // 1
      if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // 2

      i.remove();
      asyncCall.callsPerHost().incrementAndGet();
      executableCalls.add(asyncCall);//3
      runningAsyncCalls.add(asyncCall);//4
    }
    isRunning = runningCallsCount() > 0;
  }

  for (int i = 0, size = executableCalls.size(); i < size; i++) {
    AsyncCall asyncCall = executableCalls.get(i);
    asyncCall.executeOn(executorService());//5 调用下面的executeOn函数
  }

  return isRunning;
}

//AsyncCall类中
void executeOn(ExecutorService executorService) {      
      boolean success = false;
      try {
        executorService.execute(this);
        success = true;
      } catch (RejectedExecutionException e) {
        ......
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

OKHttp的线程池

 public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
//AsyncCall类中
@Override protected void execute() {
      ......
      try {
        Response response = getResponseWithInterceptorChain();//1
        ......
        responseCallback.onResponse(RealCall.this, response);//2
      } catch (IOException e) {
        ......
        responseCallback.onFailure(RealCall.this, e);
      } catch (Throwable t) {
          ......
          responseCallback.onFailure(RealCall.this, canceledException);
        }
        throw t;
      } finally {
        client.dispatcher().finished(this);
      }
    }

疑问1:线程数最大可以是Integer.MAX_VALUE,会不会撑爆虚拟机?

其实不会的,因为在Dispatcher.promoteAndExecute添加任务时,已经限制了数量;

疑问2:为什么核心线程数为0?

默认情况下,核心线程是不会被回收,除非线程池shutdown了,而其他线程可以设置超时时间,后来我想了想,核心线程数不为0,通过allowCoreThreadTimeOut设置true,也可以达到目的,只不过直接设置0比较简单;

总结

以上分析有不对的地方,请指出,互相学习,谢谢哦!

上一篇下一篇

猜你喜欢

热点阅读