OkHttp Dispatcher 源码解析

1.常用的属性

  private int maxRequests = 64; //限制最大的请求数量
  private int maxRequestsPerHost = 5; 限制ip或者域名相同时不可超过
  private @Nullable Runnable idleCallback; //空闲回调,在finished()方法触发

  /** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService;//线程调度器,异步执行靠这个的,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<>();//同步容器

  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;

 常用方法:

 /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);  //同步方法调用这个...只是添加到容器中
  }
  //异步方法
    synchronized void enqueue(AsyncCall call) {
    //判断运行中请求是否大于mxaRequests 和ip相同数量是否超过maxRequestPerHost if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call); 小于 ,添加到容器
      executorService().execute(call); 分派到子线程中执行
    } else {
      readyAsyncCalls.add(call); 大于,添加到等待容器中
    }
  }

 /** Used by {@code AsyncCall#run} to signal completion. */
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);//调用重载方法
  }

  /** Used by {@code Call#execute} to signal completion. */
  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);//调用重载方法
  }
//在网络请求完成时 不管是成功还是失败都会调用
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(); //异步方法传来的是true 所用调用 同步不调用
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run(); 符合条件 回调空闲方法
    }
  }

private void promoteCalls() {
 
 if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
   //有等待请求并运行中不超过 maxRequests 将遍历等待容器
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();
     //运行中ip 相同数量不超过MaxRequestPerhost
      if (runningCallsForHost(call) < maxRequestsPerHost) {
 i.remove();  //条件符合 从等待容器移除
        runningAsyncCalls.add(call);添加到运行容器中 
        executorService().execute(call);并分派到线程调度器中执行
}

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }
 public synchronized int runningCallsCount() {
    return runningAsyncCalls.size() + runningSyncCalls.size();
  }
  /** Returns the number of running calls that share a host with {@code call}. */
  private int runningCallsForHost(AsyncCall call) {
    int result = 0;
    for (AsyncCall c : runningAsyncCalls) {
      if (c.host().equals(call.host())) result++;
    }
    return result;
  } if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call); 小于 ,添加到容器
      executorService().execute(call); 分派到子线程中执行
    } else {
      readyAsyncCalls.add(call); 大于,添加到等待容器中
    }
  }

 /** Used by {@code AsyncCall#run} to signal completion. */
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);//调用重载方法
  }

  /** Used by {@code Call#execute} to signal completion. */
  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);//调用重载方法
  }
//在网络请求完成时 不管是成功还是失败都会调用
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(); //异步方法传来的是true 所用调用 同步不调用
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run(); 符合条件 回调空闲方法
    }
  }

private void promoteCalls() {
 
 if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
   //有等待请求并运行中不超过 maxRequests 将遍历等待容器
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();
     //运行中ip 相同数量不超过MaxRequestPerhost
      if (runningCallsForHost(call) < maxRequestsPerHost) {
 i.remove();  //条件符合 从等待容器移除
        runningAsyncCalls.add(call);添加到运行容器中 
        executorService().execute(call);并分派到线程调度器中执行
}

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }
 public synchronized int runningCallsCount() {
    return runningAsyncCalls.size() + runningSyncCalls.size();
  }
  /** Returns the number of running calls that share a host with {@code call}. */
  private int runningCallsForHost(AsyncCall call) {
    int result = 0;
    for (AsyncCall c : runningAsyncCalls) {
      if (c.host().equals(call.host())) result++;
    }
    return result;
  }


结论:Dispather 代码很简单,难点在于ExecutorService 这个类中.

 

为什么不使用ExecutorService 去控制最大的请求,而是使用maxRequests 和maxRequestPerHost在外部进行控制呢

  ExecutorService 可以使用 maximumPoolSize 代替maxRequests,但是maxRequestPerHost 呢这样是不是要重写

.还有就是我可以使用一个容器存放或者两个容器然后通过一个标记来判断是同步或者异步,等待异步.为什么使用三个........因为要遍历,分工也不明确.代码简单易懂源于代码的设计.

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值