编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

【OkHttp源码分析】三、OkHttp同步异步请求有什么区别

wxchong 2024-06-10 17:03:50 开源技术 12 ℃ 0 评论

OkHttp作为常用的网络通讯组件,其中大部分的功能点需要我们深入了解,本系列的文章将以源码角度解析组件背后的运行原理,避免踩坑。

文章中提到的okHttp版本为4.10.0,源码的git分支是4.10.x,源码git地址:https://square.github.io/okhttp/

文章概要

前面的文章我们了解了连接和连接池。这篇文章我们将深入扒一扒同步请求和异步请求的区别。

首先看下两者请求的区别

同步请求

httpClient.newCall(request).execute();

异步请求

Callback responseCallback;
httpClient.newCall(request).enqueue(responseCallback);
responseCallback.get();

首先从异步请求开始看,从enqueue方法的入参看出,请求结果通过这个类触发回调。

interface Callback {
  /**
   * 调用失败时
   */
  fun onFailure(call: Call, e: IOException)
  /**
   * 调用成功时
   */
  fun onResponse(call: Call, response: Response)
}

而enqueue方法构建了一个AsyncCall对象

override fun enqueue(responseCallback: Callback) {
  /// 省略部分代码
  client.dispatcher.enqueue(AsyncCall(responseCallback))
}

AsyncCall类实现了Runnable接口

internal inner class AsyncCall(
  private val responseCallback: Callback
)

异步请求的流程:

  • 构建一个AsyncCall对象,通过Dispatcher.kt#enqueue()放入调度池中,放入调度池第一件事是从其他的待执行的请求中共享相同host的请求数量。
  • 触发调度池发起调度,调度池会从readyAsyncCalls捞取一个请求,如果当前没有超过最大请求量和同host最大请求量,这个请求将开始执行。
  • 这个任务会被提交到Distpatcher默认executorService(无界线程池)中执行。

同步请求流程就非常简单了、省去了调度流程:

override fun execute(): Response {
    check(executed.compareAndSet(false, true)) { "Already Executed" }
    timeout.enter()
    callStart()
    try {
      client.dispatcher.executed(this)
      // 直接发起调用
      return getResponseWithInterceptorChain()
    } finally {
      client.dispatcher.finished(this)
    }
  }

总结

okhttp同步请求和异步请求的差异: 1、异步请求等待线程池调度、同步请求直接发起。2、异步请求调度有同host连接数限制、最大请求数量限制 3、异步请求通过实现传入一个Callback接口实现获取结果。

后面我们将深入分析OkHttp 4.10.0版本的事件,感兴趣的同学欢迎继续关注!

-END-

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表