【网络编程】okhttp深入理解

在这里插入图片描述
newCall 实际上是创建了一个 RealCall 有三个参数:OkHttpClient(通用配置,超时时间等) Request(Http请求所用到的条件,url等) 布尔变量forWebSocket(webSocket是一种应用层的交互方式,可双向交互,一般用不到,除非需要频繁刷新数据,股票等。)

	private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
	  this.client = client;
	  this.originalRequest = originalRequest;
	  this.forWebSocket = forWebSocket;
	}

Request会被进行多次封装(所以构造函数里对象被命名为originRequest)

在进行newCall().enqueue(),实际就是RealCallenqueue()

	@Override public void enqueue(Callback responseCallback) {
	  synchronized (this) {
	    if (executed) throw new IllegalStateException("Already Executed");
	    executed = true;
	  }
	  //1
	  transmitter.callStart();
	  //2 关键
	  client.dispatcher().enqueue(new AsyncCall(responseCallback));
	}

分别看1和2,主要看2

	public void callStart() {
	    //跟踪程序错误
	  this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()");
	  //eventListener是一个监听器,连接的接入和关闭,对程序进行监听
	  eventListener.callStart(call);
	}

client.dispatcher()返回一个Dispatcher类对象,即线程调度器,然后用这个去进行异步操作,代入参数为一个AsyncCall

	void enqueue(AsyncCall call) {
	  synchronized (this) {
	    //1
	    readyAsyncCalls.add(call);
	
	    // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
	    // the same host.
	    //2
	    if (!call.get().forWebSocket) {
	      AsyncCall existingCall = findExistingCallWithHost(call.host());
	      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
	    }
	  }
	  //3
	  promoteAndExecute();
	}
  • 1的readyAsyncCalls 是一个 ArrayDeque<AsyncCall> ,存放 准备要执行但还没有执行,然后会在3的promoteAndExecute()中执行
	private boolean promoteAndExecute() {
	  assert (!Thread.holdsLock(this));
	
	  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; // Max capacity.
	      if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
	
	      i.remove();
	      asyncCall.callsPerHost().incrementAndGet();
	      executableCalls.add(asyncCall);
	      runningAsyncCalls.add(asyncCall);
	    }
	    isRunning = runningCallsCount() > 0;
	  }
	
	  for (int i = 0, size = executableCalls.size(); i < size; i++) {
	    AsyncCall asyncCall = executableCalls.get(i);
	    asyncCall.executeOn(executorService());
	  }
	
	  return isRunning;
	}

promoteAndExecute会挑选那些不会导致超负载的call(不超过AsyncCall对应的maxRequest),放进executableCallsrunningAsyncCalls,然后去执行,就是去遍历executableCalls然后执行。
分别执行就是把调用每一个asyncCall 的 executeOn():

	void executeOn(ExecutorService executorService) {
	  assert (!Thread.holdsLock(client.dispatcher()));
	  boolean success = false;
	  try {
	    executorService.execute(this);
	    success = true;
	  } catch (RejectedExecutionException e) {
	    InterruptedIOException ioException = new InterruptedIOException("executor rejected");
	    ioException.initCause(e);
	    transmitter.noMoreExchanges(ioException);
	    responseCallback.onFailure(RealCall.this, ioException);
	  } finally {
	    if (!success) {
	      client.dispatcher().finished(this); // This call is no longer running!
	    }
	  }
	}

核心只有一行:

executorService.execute(this);

这里就已经切换线程了,执行的都是传入的 executorService.对象 的execute()方法,都会在后台执行

	@Override protected void execute() {
	  boolean signalledCallback = false;  // 标记回调是否已触发
	
	  transmitter.timeoutEnter();  // 进入超时处理逻辑
	  try {
	Response response = getResponseWithInterceptorChain();  // 调用拦截器链获取response
	    signalledCallback = true;  // 标记回调已触发
	    responseCallback.onResponse(RealCall.this, response);  // 调用response的回调函数
	  } catch (IOException e) {
	    if (signalledCallback) {
	      // 不要重复触发回调!
	      Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
	    } else {
	      responseCallback.onFailure(RealCall.this, e);
	    }
	  } catch (Throwable t) {
	     cancel();  // 取消请求
	    if (!signalledCallback) {
	      IOException canceledException = new IOException("canceled due to " + t);
	      canceledException.addSuppressed(t);
	      responseCallback.onFailure(RealCall.this, canceledException);  // 调用失败回调函数
	    }
	    throw t;
	  } finally {
	    client.dispatcher().finished(this);  // 请求结束,将请求移出调度队列
	  }
	}

其中回调函数就是当初我们在应用层所定义的Callback里边定义的onFailure()onResponse(),然后如果出现异常,会进行调用相应的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/404241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

符尧大佬一作发文,仅改训练数据,就让LLaMa-2上下文长度扩展20倍!

引言&#xff1a;探索语言模型的长上下文能力 近日&#xff0c;谷歌推出了Gemini Pro 1.5&#xff0c;将上下文窗口长度扩展到100万个tokens&#xff0c;目前领先世界。而其他语言模型也正在不断探索长上下文能力&#xff0c;也就是模型处理和理解超出其训练时所见上下文长度的…

基于飞凌嵌入式RK3568核心板的边缘计算门禁屏解决方案

边缘计算作为一种将计算任务从云端推向网络边缘的新型计算模式&#xff0c;正日益受到各行各业的青睐&#xff0c;并已在我们的生产和生活当中得到了广泛的应用&#xff0c;其中“门禁系统”就是最常见的与边缘计算相结合的应用之一。 传统的门禁系统受限于数据处理能力和网络…

2023年的AI模型学习/部署/优化

可以的话&#xff0c;github上给点一个小心心&#xff0c;感谢观看。 LDC边缘检测的轻量级密集卷积神经网络&#xff1a; meiqisheng/LDC (github.com)https://github.com/meiqisheng/LDC segment-anything分割一切的图像分割算法模型&#xff1a; meiqisheng/segment-anyt…

新手学习Cesium的几点建议

Cesium是当前非常火热的三维数字地球开发框架&#xff0c;很多公司基于Cesium做项目以及形成了自己的产品&#xff0c;关于Cesium的学习&#xff0c;有诸多网站、书籍、学习资料甚至培训教材&#xff0c;这里不再详细推荐&#xff0c;从学习Cesium的角度&#xff0c;资料和教程…

精美的WordPress外贸独立站模板

WordPress外贸独立站主题 简洁实用的WordPress外贸独立站主题&#xff0c;适合时尚服装行业搭建wordpress企业官网使用。 https://www.jianzhanpress.com/?p4999 简洁wordpress独立站模板 绿色精美、简洁大气的wordpress外贸独立网站模板 https://www.jianzhanpress.com/?…

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

微软推出Windows照片编辑新功能:AI魔术橡皮擦生成擦除工具让照片修图更轻松

微软宣布推出生成擦除功能&#xff0c;该功能让用户在 Windows 捆绑的照片应用程序中使用人工智能技术对照片进行修改。这一功能类似于谷歌和三星设备上的 AI 选择性照片橡皮擦&#xff0c;让用户可以轻松消除照片中的不需要的元素&#xff0c;如狗的皮带或意外出现的人物。不仅…

数据可视化在商业领域有哪些重要性?

数据可视化在商业领域的重要性体现在多个方面&#xff0c;它通过将复杂的数据集转化为直观、易于理解的图形和图表&#xff0c;帮助企业和组织做出更明智的决策。以下是数据可视化对商业的一些关键重要性&#xff1a; 提高决策效率&#xff1a;通过直观的图表和图形&#xff0c…

如何把电脑上的png图片变为jpg?图片格式在线转化的方法

由于jpg文件比较小&#xff0c;把png格式转换后更适合我们的保存和使用&#xff0c;尤其是对于一些平台上传来说&#xff0c;很多地方都要求图片格式为jpg&#xff0c;为了能更顺利的上传&#xff0c;本文就叫大家一个图片格式转换的方法&#xff0c;使用压缩图网站&#xff0c…

STM32Cubemx TB6612直流电机驱动

一、TB6612FNG TB6612是一个支持双电机的驱动模块&#xff0c;支持PWM调速。PWMA、AIN1、AIN2 为一组控制引脚&#xff0c;PWMA 为 PWM 速度控制引脚&#xff0c;AIN1、AIN2 为方向控制引脚&#xff1b;PWMB、BIN1、BIN2 为一组控制引脚&#xff0c;PWMB 为 PWM 速度控制引脚&…

Fpga_高斯滤波

一 算法原理 高斯滤波即将图像频域处理和时域处理相联系&#xff0c;作为低通滤波器使用&#xff0c;滤去低频能量&#xff0c;平滑图像&#xff0c;适用于消除高斯噪声&#xff0c;应用于图像降噪领域。 高斯滤波是对图像像素点进行加权平均的过程&#xff0c;某一像素点的值…

Unity编辑器内工程文件重命名|Project视图文件名修改

Unity编辑器内文件重命名 前言大项内容一使用方法代码展示 总结 前言 本文代码可以一键更改Project视图的文件名字 在当前文件名的状态下增加一段字符区分文件。 大项内容一 功能是因为在给其他人导入项目资源时有重复的资源的时候&#xff0c;资源会产生覆盖的问题。所以直…

Neo4j导入数据之JAVA JDBC

目录结构 前言设置neo4j外部访问代码整理maven 依赖java 代码 参考链接 前言 公司需要获取neo4j数据库内容进行数据筛查&#xff0c;neo4j数据库咱也是头一次基础&#xff0c;辛辛苦苦安装好整理了安装neo4j的步骤&#xff0c;如今又遇到数据不知道怎么创建&#xff0c;关关难…

C语言第二十九弹---浮点数在内存中的存储

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1、浮点数在内存中的存储 1.1、练习 1.2、浮点数怎么转化为二进制 1.3、浮点数的存储 1.3.1、浮点数存的过程 1.3.2、浮点数取的过程 1.3、题目解析…

vue 动态渲染本地图片不显示的解决方法

代码更改前 <img class"img" :src"/assets/images/${syntheticalGrade}.png" />data(){return{syntheticalGrade:"1"} }效果图&#xff1a; 解决代码 <img class"img" :src"require(/assets/images/${syntheticalGrad…

【服务器数据恢复】FreeNAS+ESXi虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器通过FreeNAS&#xff08;本案例使用的是UFS2文件系统&#xff09;实现iSCSI存储&#xff0c;整个UFS2文件系统作为一个文件挂载到ESXi虚拟化系统&#xff08;安装在另外2台服务器上&#xff09;上。该虚拟化系统一共有5台虚拟机&…

JAVAEE初阶 JVM(一)

JVM的热门话题 一. JVM中的内存区域划分1.经典笔试题. 二. JVM的类加载机制 一. JVM中的内存区域划分 1.经典笔试题. 二. JVM的类加载机制

智慧农业四情监测预警系统

TH-Q3智慧农业四情监测预警系统是指通过对农田环境、作物生长、病虫害发生以及气象变化等四种情况的实时监测和数据分析&#xff0c;实现对农业生产过程的预警和决策支持的系统。该系统集成了物联网、大数据、云计算等现代信息技术&#xff0c;为农业生产提供了全面、准确、实时…

chatGPT很能干,害不害怕被替代?

文章目录 chatGPT很能干&#xff0c;但无法做到无所不能chatGPT能帮我们做的50事情哪些职业不容易被chatGPT影响未来职业天梯总结 chatGPT很能干&#xff0c;但无法做到无所不能 利用跟chatGPT的对话&#xff0c;它告诉我们它能干点啥。 chatGPT能帮我们做的50事情 能做的事情…

Qt的跨平台开发

自从最初发布以来&#xff0c;Qt就以其跨平台的能力而闻名——这是创建这个框架背后的主要愿景。您可以在自己喜欢的桌面平台(如Windows、Linux和mac OS)上使用Qt Creator&#xff0c;并使用相同的代码库或稍加修改&#xff0c;创建流畅、现代、触摸友好的图形用户界面(GUI)和桌…