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 数据字段包含:日期,开盘价,收盘价,最低价,最高价,…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
