【网络编程】okhttp深入理解

news2024/11/15 1:47:49

在这里插入图片描述
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(),然后如果出现异常,会进行调用相应的方法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PolarDN MISC做题笔记

cat flag 使用01打开flag.png,发现图片尾部有padding的数据。D0 CF 11 E0 A1 B1 1A E1为office2007以前版本的文件头。将其另存为flag.doc,打开发现提示需要密码。&#xff08;可以注意到&#xff1a;D0CF11E0非常类似DOCFILE&#xff09; 使用john的office2john.py 提取hash …

React基础-webpack+creact-react-app创建项目

学习视频&#xff1a;学习视频 2节&#xff1a;webpack工程化创建项目 2.1.webpack工程化工具&#xff1a;vite/rollup/turbopak; 实现组件的合并、压缩、打包等&#xff1b; 代码编译、兼容、校验等&#xff1b; 2.2.React工程化/组件开发 我们可以基于webpack自己去搭建…

android studio模拟器不能打开

Andriod:The selected AVD is currently running in the Emulator. Please exit the emulator instance… 1.点击 2.删除下面文件 3.重新打开即可 参考

蓝桥杯倒计时49天!前缀和的拓展

倒计时49天&#xff01; 前缀和的拓展——压缩矩阵 最大子段和 题目描述 给出一个长度为 n n n 的序列 a a a&#xff0c;选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数&#xff0c;表示序列的长度 n n n。 第二行有 n n n 个整数&#xff0…

精美的WordPress外贸独立站模板

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

【力扣hot100】刷题笔记Day10

前言 一鼓作气把链表给刷完&#xff01;&#xff01;中等题困难题冲冲冲啊啊啊&#xff01; 25. K 个一组翻转链表 - 力扣&#xff08;LeetCode&#xff09; 模拟 class Solution:def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:# 翻转…

跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA)

跨越千年医学对话&#xff1a;用AI技术解锁中医古籍知识&#xff0c;构建能够精准问答的智能语言模型&#xff0c;成就专业级古籍解读助手&#xff08;LLAMA&#xff09; 介绍&#xff1a;首先在 Ziya-LLaMA-13B-V1基线模型的基础上加入中医教材、中医各类网站数据等语料库&am…

day16_ListSet课后练习题 - 参考答案

文章目录 day16_课后练习题第1题第2题第3题第4题第5题第6题第7题第8题 day16_课后练习题 第1题 案例&#xff1a; ​ 1、用一个String[]数组存点数 ​ 2、用一个String[]数组存花色 ​ 3、用一个String[]数组存大王、小王 ​ 4、用上面的数组&#xff0c;生成一副扑克牌 …

【寸铁的刷题笔记】树、dfs、bfs、回溯、递归(一)

【寸铁的刷题笔记】树、dfs、bfs、回溯、递归(一) 大家好 我是寸铁&#x1f44a; 总结了一篇刷题关于树、dfs、bfs、回溯、递归的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 105. 从前序与中序遍历序列构造二叉树 模拟分析图 代码实现 /*** Definition for a binary tre…

Android中Transition过渡动画的简单使用

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 一、布局xml文件代码如下&#xff1a; <?xml version"1.0" encoding&quo…

websocket与Socket的区别

概念讲解 网络&#xff1a;通俗意义上&#xff0c;也就是连接两台计算器 五层网络模型&#xff1a;应用层、传输层、网络层、数据链路层、物理层 应用层 (application layer)&#xff1a;直接为应用进程提供服务。应用层协议定义的是应用进程间通讯和交互的规则&#xff0c;不…

【结合OpenAI官方文档】解决Chatgpt的API接口请求速率限制

OpenAI API接口请求速率限制 速率限制以五种方式衡量&#xff1a;RPM&#xff08;每分钟请求数&#xff09;、RPD&#xff08;每天请求数&#xff09;、TPM&#xff08;每分钟令牌数&#xff09;、TPD&#xff08;每天令牌数&#xff09;和IPM&#xff08;每分钟图像数&#x…

网页403错误(Spring Security报异常 Encoded password does not look like BCrypt)

这个错误通常表现为"403 Forbidden"或"HTTP Status 403"&#xff0c;它指的是访问资源被服务器理解但拒绝授权。换句话说&#xff0c;服务器可以理解你请求看到的页面&#xff0c;但它拒绝给你权限。 也就是说很可能测试给定的参数有问题&#xff0c;后端…

【rust】vscode下rust-analyzer和Rust Test Lens的Lens

背景 一个粉丝问&#xff1a; 我编辑的launch.json为什么只在按F5的时候工作 按这个debug按钮就不工作&#xff1f; 那在哪改这个插件的配置文档&#xff1f;我一直用的F5 今天上午才注意到这个问题&#xff0c;比如怎么改程序的命令行参数&#xff0c;我意思是如果我非要用…

如何使用逻辑回归处理多标签问题?

逻辑回归处理多分类 1、背景描述2、One vs One 1、背景描述 逻辑回归本身只能用于二分类问题&#xff0c;如果实际情况是多分类的&#xff0c;那么就需要对模型进行一些改动。下面介绍三种常用的将逻辑回归用于多分类的方法 2、One vs One OvO&#xff08;One vs One&#xff…

【嵌入式学习】QT-Day3-Qt基础

1> 思维导图 https://lingjun.life/wiki/EmbeddedNote/20QT 2> 完善登录界面 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后…

igolang学习3,golang 项目中配置gin的web框架

1.go 初始化 mod文件 go mod init gin-ranking 2.gin的crm框架 go get -u github.com/gin-gonic/gin 3.go.mod爆红解决

C2-1.4(L1,L2)正则化

C2-1.4&#xff08;L1,L2&#xff09;正则化 参考书籍 1 正则化的概念 正则化(Regularization) 是机器学习中对原始损失函数引入额外信息&#xff0c;以便防止过拟合和提高模型泛化性能的一类方法的统称。也就是目标函数变成了原始损失函数额外项&#xff0c;常用的额外项一般…

Oladance、南卡、韶音开放式耳机怎么样?3个月真实对比测评

​哪款开放式耳机好用&#xff1f;我亲自体验并评测了市场上流行的三个品牌的开放式耳机&#xff1a;Oladance、南卡、韶音。通过深入测试多维度性能表现&#xff0c;确保你能够远离劣质产品可能带来的问题。我想提醒大家&#xff0c;如果选错耳机可能会影响到音乐的真实还原和…

【高德地图】Android搭建3D高德地图详细教

&#x1f4d6;Android搭建3D高德地图详细教程 &#x1f4d6;第1章 高德地图介绍✅了解高德地图✅2D地图与3D地图 &#x1f4d6;第2章 搭建3D地图并显示✅第 1 步&#xff1a;创建 Android 项目✅第 2 步&#xff1a;获取高德Key✅第 3 步&#xff1a;下载地图SDK✅第 4 步&…