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

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

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

如何构建适合自己的DevOps软件测试改进方案

​目录 DevOps成熟度模型分析 构建适合企业自身性能的测试过程改进框架 资料获取方法 根据2022年的DevOps全球调查报告显示&#xff0c;主流软件企业采用或部分采用DevOps且已获得良好成效的占比已达70%&#xff0c;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对象&#xff0c;指定要连接的服务器地址与端口 建立连…...

【yolov8系列】将yolov8-seg 模型部署到瑞芯微RK3566上

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

Java类的默认构造函数

什么情况下存在默认构造函数 说明 如果一个Java类没有显式包含构造函数的声明&#xff0c;那么隐含着有一个默认构造函数。 示例 定义一个类B&#xff0c;没有显式声明构造函数&#xff0c;所以存在一个默认构造函数&#xff1a; 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 重新上线,带来全新体验!

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

动态内存管理面试题

动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下&#xff08;示例&#xff09;&#xff1a; #include<stdio.h> #include<string.h> #incl…...

树莓派外设开发编程

目录 一、树莓派的接口&#xff1a;驱动 二、wiringPi 库 1.在使用wiringPi库的时候&#xff0c;需要包含头文件 2.wiringPi库API 一、树莓派的接口&#xff1a;驱动 IO口&#xff1a;input output 对于主控来说 Input &#xff1a;人体、烟雾、振动 output: 继电…...

Java从入门到精通(一)

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

Electron从构建到打包程exe应用

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

3分钟学会设计模式 -- 单例模式

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

《面试1v1》Kafka与传统消息系统区别

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…...

【算法第十三天7.27】平衡二叉树,二叉树所有路径,左叶子之和

链接力扣110-平衡二叉树 思路 1、左右子树高度差不超过1 2、左子树、右子树均为平衡二叉树 3、需要获得树高&#xff0c;如果不是平衡的就返回-1&#xff1b;如果是平衡&#xff0c;就返回对应的高 class Solution {public boolean isBalanced(TreeNode root) {return getH…...

arm架构cloudstack的agent报错No more available PCI slots如何解决

当ARM架构的CloudStack代理报错"No more available PCI slots"时&#xff0c;这通常表示ARM实例已用尽可用的PCI插槽。PCI插槽用于连接网络接口卡&#xff08;NIC&#xff09;和其他扩展设备到虚拟机实例。 解决此问题的方法可以考虑以下几点&#xff1a; 调整实例的…...

day43-Feedback Ui Design(反馈ui设计)

50 天学习 50 个项目 - HTMLCSS and JavaScript day43-Feedback Ui Design&#xff08;反馈ui设计&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&q…...

TypeScript基础篇 - TS日常类型 上篇

目录 TS的常见用法介绍 example01.ts 逃避类型检查&#xff1a;any 思考一下~&#xff1a;不知道类型 类型标注 函数&#xff08;参数和返回值&#xff09; 匿名函数 TS如何知道匿名函数的类型&#xff1f; TS是一种标注式语言&#xff0c;不侵入JS的设计 TS的常见用法…...

量化交易——python数据分析及可视化

该项目分为两个部分&#xff1a;一是数据计算&#xff0c;二是可视化&#xff0c;三是MACD策略 一、计算MACD 1、数据部分 数据来源&#xff1a;tushare 数据字段包含&#xff1a;日期&#xff0c;开盘价&#xff0c;收盘价&#xff0c;最低价&#xff0c;最高价&#xff0c…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...