Kotlin 协程 CoroutineScope
协程定义:
19年官方是这样说的:协程是轻量级的线程,协程就是 Kotlin 提供的一套线程封装的 API;
现在官方是这样说的:协程是一种并发设计模式;
协程作用:
1.处理耗时任务;
2.保证主线程的安全;
3.简化异步执行的代码,解决并发问题,让「协作式多任务」实现起来更加方便。
使用协程,同样可以像 Rx 那样有效地消除回调地狱,不过无论是设计理念,还是代码风格,两者是有很大区别的,协程在写法上和普通的顺序代码类似。
协程特点:
轻量:您可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
内置取消支持:取消功能会自动通过正在运行的协程层次结构传播。
协程使用:
1.lauch
lauch用于在协程作用域中异步启动一个新的协程,调用该方法不会阻塞线程。
CoroutineScope(Dispatchers.IO).launch {// 启动一个非阻塞线程的协程
}
2.suspend
suspend是协程的关键字,每一个被suspend修饰的方法都必须在另一个suspend函数或者Coroutine协程程序中进行调用。
3.coroutineScope
coroutineScope是一个挂起函数,每一个被suspend修饰的方法都必须在另一个suspend函数或者Coroutine协程程序中进行调用。
CoroutineScope(Dispatchers.IO).launch {coroutineScope {// 启动一个非阻塞线程的协程}
}runBlocking {coroutineScope {// 启动一个非阻塞线程的协程}
}
4.runBlocking
runBlocking会阻塞当前线程,而coroutineScope不会阻塞所在的线程,它会挂起所在的协程直至其内部任务(包括子协程)执行完成。
runBlocking {// 启动一个阻塞线程的协程
}
5.dispatcher
dispatcher 协程调度器,可以控制协程代码块在UI线程还是子线程中执行;
6.async
1)在概念上,async 就类似于 launch。它启动了一个单独的协程与其它所有的协程一起并发的工作。不同之处在于 launch 返回一个 Job 并且不附带任何结果值,而 async 返回一个 Deferred接口指向的对象,使用 Deferred.await()在一个延期的值上得到它的最终结果,同时Deferred 也是一个 Job,所以如果需要的话,可以使用Deferred.cancel()取消它。
CoroutineScope(Dispatchers.IO).launch {val api1Deferred = async { api1() }val api2Deferred = async { api2() }val api3Deferred = async { api3() }println("api*****1")val result1 = api1Deferred.await()println("api*****2")
}suspend fun api1(): String {delay(2500) // 模拟耗时操作println("api1")return "api1"
}suspend fun api2(): String {delay(2000) // 模拟耗时操作println("api2")return "api2"
}suspend fun api3(): String {delay(1500) // 模拟耗时操作println("api3")return "api3"
}
输出结果:
结论:
async启动的所有协程是一起并发工作的,async不是挂起函数,所以不会挂起launch创建的协程,所以先输出api*****1,再api3、api2、api1,但执行到api1Deferred.await()时,会挂起协程,等待async { api1() }执行完返回结果后,再执行协程后续的函数,所以最后输出api*****2,因为await()是挂起函数。
public suspend fun await(): T
2)案例:有4个耗时方法,方法名api1,api2,api3,api4;要求方法api1先执行,返回String "api1",然后将结果"api1"作为参数,并发执行方法api2和方法api3,由于api3 delay(1500),api2 delay(2000),所以api3会先执行完并输出结果,然后api2再执行完并输出结果,最后将结果"api2",api3"作为参数,执行方法api4。
CoroutineScope(Dispatchers.IO).launch {val api1Deferred = async { api1() }println("api*****1")val result1 = api1Deferred.await()println("api1:$result1") // 等待 api1 方法执行完成并输出结果val api2Deferred = async { api2(result1) }val api3Deferred = async { api3(result1) }val result2 = api2Deferred.await()println("api2:$result2")val result3 = api3Deferred.await()println("api3:$result3")println(api4(result2, result3))
}suspend fun api1(): String {delay(3000) // 模拟耗时操作println("api1")return "api1"
}suspend fun api2(v: String): String {delay(2000) // 模拟耗时操作println("api2")return "api2:$v"
}suspend fun api3(v: String): String {delay(1500) // 模拟耗时操作println("api3")return "api3:$v"
}suspend fun api4(v: String, v2: String): String {delay(500) // 模拟耗时操作return "api4:$v$v2"
}
输出结果:
注:async是并行的,如果使用await()的话,await()是挂起函数,会挂起协程,等待async { api1() }执行完返回结果后,再执行协程后续的函数。
7. withContext
withContext 与 async 都可以返回耗时任务的执行结果。多个 withContext 任务是串行(顺序执行)的, 且withContext 可直接返回耗时任务的结果。 而多个 async 任务是并行的。
public suspend fun <T> withContext()
因为withContext()是挂起函数,执行后,会挂起协程,等待withContext内部函数执行完后,再执行withContext函数后面的函数。
CoroutineScope(Dispatchers.IO).launch {val result1 = withContext(Dispatchers.IO) {api1()}println("api*****1")println("api1:$result1") // 等待 api1 方法执行完成并输出结果val result2 = withContext(Dispatchers.IO) {api2(result1)}println("api2:$result2")val result3 = withContext(Dispatchers.IO) {api3(result1)}println("api3:$result3")val result4 = withContext(Dispatchers.IO) {api4(result2, result3)}println(result4)
}suspend fun api1(): String {delay(3000) // 模拟耗时操作println("api1")return "api1"
}suspend fun api2(v: String): String {delay(2000) // 模拟耗时操作println("api2")return "api2:$v"
}suspend fun api3(v: String): String {delay(1500) // 模拟耗时操作println("api3")return "api3:$v"
}suspend fun api4(v: String, v2: String): String {delay(500) // 模拟耗时操作return "api4:$v$v2"
}
输出结果:
相关文章:

Kotlin 协程 CoroutineScope
协程定义: 19年官方是这样说的:协程是轻量级的线程,协程就是 Kotlin 提供的一套线程封装的 API; 现在官方是这样说的:协程是一种并发设计模式; 协程作用: 1.处理耗时任务; 2.保…...

如何构建适合自己的DevOps软件测试改进方案
目录 DevOps成熟度模型分析 构建适合企业自身性能的测试过程改进框架 资料获取方法 根据2022年的DevOps全球调查报告显示,主流软件企业采用或部分采用DevOps且已获得良好成效的占比已达70%,DevOps俨然成为当下软件开发研究的重要方向。 测试作为软…...
PHP关于字符串的各类处理方法
判断字符串是否以指定子串开头或结尾 function startsWith($str, $prefix) {return stripos($str, $prefix) 0; }function endsWith($str, $suffix) {return substr_compare($str, $suffix, -strlen($suffix)) 0; }// 示例用法 $text "hello world"; $result st…...

Springboot+MyBatis使用
目录 依赖 配置信息 xml文件 mapper接口 打印日志 分页查询 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>my…...
WebSocketServer的使用(@ServerEndpoint)
前端代码 function initWebSocket() {if (typeof WebSocket "undefined") {console.log("您的浏览器不支持WebSocket");} else {console.log("您的浏览器支持WebSocket");//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连…...

【yolov8系列】将yolov8-seg 模型部署到瑞芯微RK3566上
前言 之前记录过【yolov5系列】将模型部署到瑞芯微RK3566上,整体比较流畅,记录了onnx转rknn的相关环境配置,使用的rk版本为rknn-toolkit2-v1.4.0。当前库已经更新为1.5,这里还是沿用1.4的版本进行记录。本篇博客是在上篇博客&…...

Java类的默认构造函数
什么情况下存在默认构造函数 说明 如果一个Java类没有显式包含构造函数的声明,那么隐含着有一个默认构造函数。 示例 定义一个类B,没有显式声明构造函数,所以存在一个默认构造函数: package com.thb;public class B {public …...

华为openGauss数据库入门 - gsql用法
目录 1.1 gsql的语法 1.2 gsql常用选项 1.2.1 最常用的必要选项 1.2.2 -r选项 1.2.3 -E选项 1.2.4 -t选项 1.2.5 -A选项 1.2.6 -v选项 1.2.7 -c选项 1.2.8 -f选项 1.2.9 -q选项 1.3 gsql的元命令 1.3.1 \l命令 1.3.2 \du命令和\dg命令 1.3.3 \db命令 1.3.4 \d…...

The Sandbox 重新上线,带来全新体验!
在经历了一个充满史诗般新回忆的全力开局后,我们短暂休息了片刻,为玩家准备了全新的、惊心动魄的游戏活动。 我们已经完成了功能的微调,准备将您的游戏体验提升到一个全新高度! 想知道我们正在做什么吗?现在还无法公开…...

动态内存管理面试题
动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下(示例): #include<stdio.h> #include<string.h> #incl…...
树莓派外设开发编程
目录 一、树莓派的接口:驱动 二、wiringPi 库 1.在使用wiringPi库的时候,需要包含头文件 2.wiringPi库API 一、树莓派的接口:驱动 IO口:input output 对于主控来说 Input :人体、烟雾、振动 output: 继电…...

Java从入门到精通(一)
Java从入门到精通(一) 前言 温故而知新,闲着没事干,准备将Java编程语言的知识点从头梳理一遍,整理成笔记,逐篇发布。 部分图片素材来源与B站“黑马程序员”的课程。 一 Java背景 Java是1995年 由Sun公司…...

Electron从构建到打包程exe应用
Electron从构建到打包程exe应用 Electron文档搭建网页装载到 BrowserWindow中定义全局对象进程之间通信渲染器进程到主进程(单向)渲染器进程到主进程(双向)主进程到渲染器进程 打开调试器打包应用程序对代码进行签名 Electron文档…...

3分钟学会设计模式 -- 单例模式
►单例模式 ►使用场景 在编写软件时,对于某些类来说,只有一个实例很重要。例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统中可以多次查询数据库,但是只需要一个连接&#x…...

《面试1v1》Kafka与传统消息系统区别
🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪 🍅 技术交流:定期更新Java硬核干货,不定期送书活动 🍅 王哥多年工作总结:Java学习路线总结…...
【算法第十三天7.27】平衡二叉树,二叉树所有路径,左叶子之和
链接力扣110-平衡二叉树 思路 1、左右子树高度差不超过1 2、左子树、右子树均为平衡二叉树 3、需要获得树高,如果不是平衡的就返回-1;如果是平衡,就返回对应的高 class Solution {public boolean isBalanced(TreeNode root) {return getH…...
arm架构cloudstack的agent报错No more available PCI slots如何解决
当ARM架构的CloudStack代理报错"No more available PCI slots"时,这通常表示ARM实例已用尽可用的PCI插槽。PCI插槽用于连接网络接口卡(NIC)和其他扩展设备到虚拟机实例。 解决此问题的方法可以考虑以下几点: 调整实例的…...

day43-Feedback Ui Design(反馈ui设计)
50 天学习 50 个项目 - HTMLCSS and JavaScript day43-Feedback Ui Design(反馈ui设计) 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&q…...
TypeScript基础篇 - TS日常类型 上篇
目录 TS的常见用法介绍 example01.ts 逃避类型检查:any 思考一下~:不知道类型 类型标注 函数(参数和返回值) 匿名函数 TS如何知道匿名函数的类型? TS是一种标注式语言,不侵入JS的设计 TS的常见用法…...

量化交易——python数据分析及可视化
该项目分为两个部分:一是数据计算,二是可视化,三是MACD策略 一、计算MACD 1、数据部分 数据来源:tushare 数据字段包含:日期,开盘价,收盘价,最低价,最高价,…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...