当前位置: 首页 > news >正文

android kotlin 协程(四) 协程间的通信

android kotlin 协程(四) 协程间的通信

学完本篇你将会了解到:

  • channel
  • produce
  • actor
  • select

先来通过上一篇的简单案例回顾一下挂起于恢复:

fun main() {val waitTime = measureTimeMillis {runBlocking<Unit> {println("main start")            // 1   // 调度前launch {println("launch 1 start")    // 2   // 调度后(执行前)delay(1000)                					// 延迟1s (不会阻塞兄弟协程)println("launch 1 end")      // 3}println("main mid")              // 4   // 调度前launch {println("launch 2 start")    // 5   // 调度后执行delay(500)                 					// 延迟0.5s (不会阻塞兄弟协程)println("launch 2 end")      // 6}println("main end")              // 7   // 调度前}}println("等待时间:${waitTime}")
}

通过上一篇我们知道了在协程中,

是会先执行调度前的代码,然后会执行调度后的代码, 直到调度后的时候,才会真正的执行到协程体中

所以这段代码的执行顺序为:

1,4,7,2,5,6,3

launch{} 中的lambda表达式 是一个suspend 函数标记的,所以始终是异步的,并不会阻塞兄弟协程

所以等待时间 约等于 1000

这里为什么说是约等于呢? 因为创建协程等一系列操作会稍微耗时一点,直接取整即可!

Channel

send / receive

channel是用来协程之前通信的,例如现在有一个需求,B协程需要使用A协程中的某个值,那么就用到了channel

先来看个最简单的例子

image-20230217133712320

可以看出,A协程可以完成发送,并且B协程也可以完成接受

如果说A协程是一个网络接口,会返回数据,此时B协程是否还会等待A协程数据返回呢?

image-20230217134057270

可以看出,即使是A协程会延迟2s,那么B协程也会等待A协程返回

如果说,A协程现在有3条数据要发送,B协程是否会接受3条呢?

image-20230217134602704

那么就要介绍 Channel()的第一个参数了:

  • capacity 通道容量

channel 类似于一个阻塞队列(BlockingQueue), 默认是只缓存1条数据,只要不取,那么新的数据就无法加入到容器中

当send第二条数据的时候, 发现并没有receive() 来取第二条数据,所以就会出现一直挂起的效果

此时我们只需要让channel通道中容量变大,多存放几条数据即可

例如这样:

image-20230217142836865

如果说,我们不想改变通道容量的大小,并且, 还要不让他挂起,那么就要介绍 channel的第二个参数了:

  • onBufferOverflow

从名字也可以看出,这是缓冲区溢出策略,一共有三种状态

  • BufferOverflow.SUSPEND: 挂起策略,当send不进去数据的时候,始终挂起,等待 receive() [默认]
  • BufferOverflow.DROP_OLDEST: 当要溢出的时候,删除缓冲区中最旧的值
  • BufferOverflow.DROP_LASTEST: 当要溢出的时候,删除缓冲区中最新的值

还是上面的例子,我们将容量设置为1, 往 channel中send 3条数据来看看效果

BufferOverflow.DROP_OLDESTBufferOverflow.DROP_LASTEST
image-20230217170914395image-20230217171031687

目前这些代码应该很好理解!

trySend / tryReceive

在新版的channel更新的api中,还增添了一系列 tryXXapi

来看一段代码:

image-20230218134149723

  • trySend() 尝试向channel中发送数据。这个函数会立即返回一个结果,表明是否成功将元素发送到通道中。如果通道已满,它会立即返回一个Failure类型的结果,否则会返回一个Success类型的结果。一般来说,生产者协程使用 trySend 函数来尝试将数据发送到通道中,不会阻塞协程,同时可以通过返回结果来判断是否成功发送数据。
  • tryReceive() 这个函数会立即返回一个结果,表明是否成功从通道中接收到元素。如果通道已空,它会立即返回一个Failure类型的结果,否则会返回一个Success类型的结果。一般来说,消费者协程使用 tryReceive 函数来尝试从通道中接收数据,不会阻塞协程,同时可以通过返回结果来判断是否成功接收数据。
// TODO =================== trySend / tryReceive ======================
fun main() = runBlocking<Unit> {// 用来协程间的通信val channel = Channel<String>(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)println("main start")launch { // A协程
//        channel.close()val trySend = channel.trySend("A协程发送数据 1")if (trySend.isSuccess) {println("channel 发送成功")} else if (trySend.isClosed) {println("channel 关闭了")} else if (trySend.isFailure) {println("channel 发送失败")}}.join() // A协程必须执行完,通道有数据了之后才能取val tryReceive = channel.tryReceive()if (tryReceive.isSuccess) {println("tryReceive 接收到了数据:${tryReceive.getOrNull()}")} else if (tryReceive.isClosed) {println("tryReceive 关闭了")} else if (tryReceive.isFailure) {println("tryReceive 发送失败")}println("main end")
}

运行结果:

image-20230220133929092

还有一些比较老的方法例如:

  • offer / poll 等一些淘汰的方法就不说了,

onSend / onReceive

还有最后一种发送,获取数据的方式,这种方式是通过select 选择器来实现的,先来看代码

 TODO =================== onSend / onReceive ======================
fun main() = runBlocking<Unit> {// 用来协程间的通信val channel = Channel<String>(capacity = 5, onBufferOverflow = BufferOverflow.SUSPEND)println("main start")launch {    // A 协程 发送数据channel.send("send发送数据 ")channel.trySend("trySend发送数据")}//  select 接收数据 默认会挂起,等待数据返回select {channel.onReceive {println("onReceive:$it")}}println("result ${channel.receive()}")channel.invokeOnClose {println("channel close ")}println("main end")
}

运行结果:

image-20230218152701375

select作用不止这些,目前了解可以接受即可,下面会重点提到!

这里有一个小知识:

如果看到有这种Select开头的,基本都是要写到select{} 中才能使用

image-20230218150450649

运行结果:

image-20230218150240659

select 下面会提到,这里就不重点说了.

在实际开发中,对于我来说,channel用的还是比较少, 我感觉这玩意比较坑,一般情况下,要实现2个协程通信,我会采用flow

例如这样:

image-20230220151404613

这篇重点不是flow,这里就不多说了!

produce / actor

produce

produce意为生产者, 其本质就是对协程和channel的一层封装,

它返回一个 ReceiveChannel 对象,这个对象可以用于在其他协程中消费 生产者协程产生的数据。

使用很简单

image-20230218153514189:

api还是调用的channel的,对我们来说只是省略了, new Channel() 的过程,这里就不多说了

actor

actor 与produce正好相反

actor本质也是对协程与channel的封装, 它会返回一个SendChannel对象,这个对象用来给协程体发送数据

image-20230220135911322

select

定义: 一旦某个挂起函数返回结果,select 结构就会立即返回该函数的结果,而其他仍在等待的挂起函数将会被取消。

注意点: select 只能用于挂起函数(即使用 suspend 修饰的函数)。另外,select 的选择器表达式中每个分支都应该返回相同类型的值,否则会编译报错。

简单的说就是, select 可以找到哪一个协程执行最快, 吧执行最快的结果返回,其他执行慢的,或者没有执行的协程全部关闭!

假设我们现在有一个实际的应用场景:

在实际开发中,我们需要请求接口, 请求接口的之前需要判断是否有缓存,

如果有缓存,就使用缓存数据

但是,如果请求接口比读取缓存数据还快,那么我们就用请求出来的数据

一般情况下缓存永远比请求数据快,这里就举个例子

image-20230220142302331

select不仅可以监听 async的返回, 还有很多用处,例如可以监听协程是否执行完, 并且返回最快执行完的协程

来看看代码:

image-20230220143320288

完整代码

下篇预告:

  • suspendCoroutine{}
  • suspendCancellableCoroutine{}
  • suspend 与 continuation与状态机器
  • 不通过协程运行 suspend函数

原创不易,您的点赞就是对我最大的帮助!

相关文章:

android kotlin 协程(四) 协程间的通信

android kotlin 协程(四) 协程间的通信 学完本篇你将会了解到: channelproduceactorselect 先来通过上一篇的简单案例回顾一下挂起于恢复: fun main() {val waitTime measureTimeMillis {runBlocking<Unit> {println("main start") // 1 // …...

苹果手机通讯录突然没了怎么恢复?

手机成为生活中的必需品&#xff0c;都会存储着各种数据文件&#xff0c;比如我们使用过的APP、音乐、照片、通讯录等通常都是存在这里面的。但我们的操作难免会有意外&#xff0c;有的是手动不小心删的&#xff0c;有的是误删的&#xff0c;有的是自己孩子删的等&#xff0c;却…...

BI知识全解,值得收藏

2021年度&#xff0c;中国商业软件市场的增长趋势是快速增长的&#xff0c;达到7.8亿美元&#xff0c;同比增长34.9%。商业智能BI在企业应用中具有巨大的价值&#xff0c;并逐渐成为现代企业信息化和数字化转型的基础。所以&#xff0c;全面了解BI&#xff0c;对于企业管理是非…...

【机器学习】GBDT

1.什么是GBDT GBDT(Gradient Boosting Decision Tree)&#xff0c;梯度提升树。它是一种基于决策树的集成算法。其中Gradient Boosting 是集成方法boosting中的一种算法&#xff0c;通过梯度下降来对新的学习器进行迭代。它是利用损失函数的负梯度方向在当前模型的值作为残差的…...

C#开发的OpenRA游戏高性能内存访问的方法

C#开发的OpenRA游戏高性能内存访问的方法 一个游戏性能往往是比较关键的, 因为游戏很多时候是比拼的是人的速度和技巧。 比如王者荣耀里,一个大招是否及时地放得出来,就会影响到一场比赛的关键。 而这个大招的释放,又取决于游戏运行在手机上的性能。 如果游戏太耗性能,导致…...

【elasticsearch】elasticsearch es读写原理

一、前言&#xff1a; 今天来学习下 es 的写入原理。 Elasticsearch底层使用Lucene来实现doc的读写操作&#xff1a; Luence 存在的问题&#xff1a; 没有并发设计 lucene只是一个搜索引擎库&#xff0c;并没有涉及到分布式相关的设计&#xff0c;因此要想使用Lucene来处理海量…...

数据在内存中的存储【上篇】

文章目录⚙️1.数据类型的详细介绍&#x1f529;1.1.类型的基本归类⚙️2.整型在内存中的存储&#x1f529;2.1.原码、反码、补码&#x1f529;2.2.大小端的介绍⚙️1.数据类型的详细介绍 &#x1f973;基本的内置类型 &#xff1a; &#x1f4a1;char ---------- 字符数据类型…...

慕了没?3年经验,3轮技术面+1轮HR面,拿下字节30k*16薪offer

前段时间有个朋友出去面试&#xff0c;这次他面试目标比较清晰&#xff0c;面的都是业务量大、业务比较核心的部门。前前后后去了不少公司&#xff0c;几家大厂里&#xff0c;他说给他印象最深的是字节3轮技术面1轮HR面&#xff0c;他最终拿到了30k*16薪的offer。第一轮主要考察…...

「可信计算」与软件行为学

可信计算组织&#xff08;Ttrusted Computing Group,TCG&#xff09;是一个非盈利的工业标准组织&#xff0c;它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立&#xff0c;并采纳了由可信计算平台联盟&#xff08;the Trusted Computing Platform Alli…...

华为OD机试题 - 找字符(JavaScript)| 代码+思路+重要知识点

最近更新的博客 华为OD机试题 - 字符串加密(JavaScript) 华为OD机试题 - 字母消消乐(JavaScript) 华为OD机试题 - 字母计数(JavaScript) 华为OD机试题 - 整数分解(JavaScript) 华为OD机试题 - 单词反转(JavaScript) 使用说明 参加华为od机试,一定要注意不要完全背…...

Linux 进程启动方法

现实中程序编写的时候&#xff0c;经常会碰到一些这样需求&#xff1a;调用系统命令&#xff0c;完成一些操作&#xff0c;或判定结果 或获取结果作为启动进程&#xff0c;调用第三方进程&#xff0c;并监控进程是否退出加载升级进程&#xff0c;升级进程kill调用者或调用者自行…...

CLEVE:事件抽取的对比预训练

CLEVE: Contrastive Pre-training for Event Extraction 论文&#xff1a;CLEVE: Contrastive Pre-training for Event Extraction (arxiv.org) 代码&#xff1a;THU-KEG/CLEVE: Source code for ACL 2021 paper “CLEVE: Contrastive Pre-training for Event Extraction” (g…...

【C++】AVLTree——高度平衡二叉搜索树

文章目录一、AVL树的概念二、AVL树节点的定义三、AVL树的插入四、AVL树的旋转1.左单旋2.右单旋3.左右双旋4.右左双旋五、进行验证六、AVLTree的性能个人简介&#x1f4dd; &#x1f3c6;2022年度博客之星Top18;&#x1f3c6;2022社区之星Top2;的&#x1f947;C/C领域优质创作者…...

软考中级-嵌入式系统设计师(二)

1、逻辑电路&#xff1a;组合逻辑单路、时序逻辑电路。根据电路是否有存储功能判断。 2、组合逻辑电路 指该电路在任一时刻的输出&#xff0c;仅取决于该时刻的输入信号&#xff0c;而与输入信号作用前电路的状态无关。一般由门电路组成&#xff0c;不含记忆元器件&#xff0…...

epoll 笔记

maxevents 参数大小一般不超过64必须够了 maxevents 个事件&#xff0c;才会传到用户空间吗&#xff1f;可见&#xff0c;只要有事件就可以传到用户空间。一台服务器可以支撑多少个链接https://blog.csdn.net/mijichui2153/article/details/81331345 0、两台虚拟机的初始状态如…...

vue(5)

文章目录1. 监测数据原理1.1 通过问题引出1.2 开始1.3 Vue.set() 方法1.4 vue 监视 数组1.5 小练习2. 收集表数据3. 过滤器4. 内置指令4.1 v-text4.2 v-html4.3 v-cloak4.4 v-once4.5 v-pre1. 监测数据原理 1.1 通过问题引出 1.2 开始 要想解决上面的这个问题 &#xff0c;需要…...

Android OTA 相关工具(一) 虚拟 A/B 之 snapshotctl

Android 虚拟 A/B 分区推出快三年了&#xff0c;不论是 google 还是百度结果&#xff0c;除了源代码之外&#xff0c;竟然没有人提到这个 Android Virtual A/B 的调试工具 &#xff0c;着实让人感觉意外。 所以我相信还有不少人不知道 Android OTA 到底都有哪些调试工具&#…...

QT for Android BLE Bluetooch QT BLE

小白式的介绍&#xff0c;很详细了&#xff0c;很多主要内容写在程序的注释里&#xff0c;慢慢看 下面是我的源码 https://download.csdn.net/download/qq_27620407/87464307 源码打不开的话可以试试下图的操作&#xff0c;之后电机确定&#xff0c;可能是加图标搞的&#xff0…...

【蓝桥集训】第四天——双指针

作者&#xff1a;指针不指南吗 专栏&#xff1a;Acwing 蓝桥集训每日一题 &#x1f43e;或许会很慢&#xff0c;但是不可以停下&#x1f43e; 文章目录1.字符串删减2.最长连续不重复子序列3.数组元素的目标和1.字符串删减 给定一个由 n 个小写字母构成的字符串。 现在&#xff…...

List<Map<String, Object>>的数据结构的添加和删除实例

对List<Map<String, Object>>的数据结构的添加和删除实例添加//初始化List<Map<String, Object>> products new ArrayList<Map<String,Object>>();//也可以这样初始化List<Map<String, Object>> products null//初始Map<…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...