OkHttp的任务调度

OkHttp的任务调度

    • 实现同步异步请求
    • dispatcher()源码
      • 线程池
      • enqueue
    • 两个队列
    • 缓存请求的异步队列的执行时间

实现同步异步请求

同步:excute()
异步:enqueue()
发送的同步/异步请求都会在dispatcher中管理其状态
作用:维护请求的状态(包括同步和异步)并维护了一个线程池(更高效的执行异步请求),用于执行相应的请求。维护任务队列
通过Call(call本质就是一个Runnable)进行封装,通过dispatcher把执行的请求推到就绪请求队列中。
OkHttp的任务调度_第1张图片

dispatcher()源码

一个线程池,两个请求队列

 private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
  private Runnable idleCallback;

  /** Executes calls. Created lazily. */
  private ExecutorService executorService;

  /** 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<>();

  public Dispatcher(ExecutorService executorService) {
    this.executorService = executorService;
  }

  public Dispatcher() {
  }

线程池

//线程池
  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; 
    }

0:核心线程池数量,空闲一段时间之后就会将所有的线程进行销毁
Integer.MAX_VALUE:最大的线程数,任务过来的时候可以无限的扩充线程的最大值,由于受到maxRequests限制,也不是可以无限创建的
60:当线程数大于核心线程数,多余的线程的最大存活时间
比如:开启20个并发请求,就会有20个请求,线程池就会在60s时候相继关闭所有无用的线程。

enqueue

synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);//线程池负责自动创建,销毁以及线程的管理
    } else {
      readyAsyncCalls.add(call);//异步请求加入就绪队列当中,进行缓存等待的操作
    }

两个队列

Dispatcher生产者,默认在主线程执行
ExecutorService,消费者池
两个队列一个用于缓存,一个用于执行任务

 /** 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<>();

判断最大请求数以及相同主机最大请求数判断,满足的话就可以进入到队列中立即执行,如果不满足,说明执行队列中存满了,就会进入到就绪队列中,等运行队列中有空间了,再把缓存的队列放入到执行队列当中,任务完成之后会调用promoteCall()方法,手动清除缓存区。

缓存请求的异步队列的执行时间

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;
    }

calls.remove():把异步请求从正在执行的异步请求的队列中删除
promoteCalls():调整任务队列的,由于同步和异步都是不安全的,所以他需要在 synchronized中进行。
runningCallsCount():正在执行的异步请求和同步请求的数目总和

你可能感兴趣的:(Android)