Kotlin协程中withContext、async 和 launch 的区别

文章目录

  • 一、withContext、async和launch对比
    • 1. withContext
    • 2. async
    • 3. launch
    • 总结对比
      • 任务启动:
      • 适用情境:
  • 二、为何说 withContext是顺序执行
    • 1. 挂起协程但不创建新协程
    • 2. 顺序流程的保证
    • 3. 用例场景的体现
    • 结论

withContext、async和launch是Kotlin协程库中用来管理并发和异步任务的三个不同的构建器。它们适用于不同的场景,具有不同的功能和用法。以下是它们之间的主要区别:

一、withContext、async和launch对比

1. withContext

功能:用于切换协程的执行上下文(例如从主线程切换到IO线程),不会创建新的并发任务。
返回值:返回协程代码块中最后一个表达式的结果。
执行方式:顺序执行,不会启动新的协程,当前协程挂起直至withContext代码块执行完成。
用法场景:适用于需要在指定上下文中执行任务的场景,特别是密集型计算或IO操作。
线性顺序:withContext是顺序执行的,代码在withContext调用时会被挂起,直到其内代码块执行完毕。

import kotlinx.coroutines.*fun main() = runBlocking {val result = withContext(Dispatchers.IO) {// 在IO线程中执行performIoOperation()}println("Result: $result")
}suspend fun performIoOperation(): String {delay(1000L)  // 模拟耗时操作return "Completed"
}

2. async

功能:用于并发地启动一个新的协程,并适合需要返回结果的任务。
返回值:返回一个Deferred对象,通过调用await()获取结果。
执行方式:并行执行。多个async可以同时启动并发任务。
用法场景:适合需要并行计算的场景,尤其是需要合并多个异步操作的结果。
非阻塞:async本身不阻塞当前线程,await会让调用者等待结果。
示例1:

val deferred: Deferred<ResultType> = async {// 执行一些并发任务someComputation()
}
val result = deferred.await()

示例2:

import kotlinx.coroutines.*fun main() = runBlocking {val deferredOne = async { performTask1() }val deferredTwo = async { performTask2() }println("Task One Result: ${deferredOne.await()}")println("Task Two Result: ${deferredTwo.await()}")
}suspend fun performTask1(): String {delay(1000L)  // 模拟耗时任务return "Result One"
}suspend fun performTask2(): String {delay(2000L)  // 模拟耗时任务return "Result Two"
}

3. launch

功能:用于启动一个新的协程,不会返回结果(不适用于需要直接返回结果的场景)。
返回值:返回一个Job对象,表示协程的生命周期,可以用来取消任务。
执行方式:并行执行。多个launch同时启动,并发地处理任务。
用法场景:适合处理不关心返回结果的异步任务,比如更新UI、发送网络请求等。
示例:

launch {// 执行一些与返回结果无关的异步任务performSomeAction()
}

总结对比

任务启动:

withContext:不启动新协程,仅切换上下文,协程挂起直至块完成。
async:启动新协程,适合需要结果的并发任务。
launch:也启动新协程,但不关注返回值,更关注任务的执行及生命周期管理。

适用情境:

  • withContext适合需要在线性代码中切换执行环境的场景。
  • async在需要合并多个异步结果的情况下很有用,例如发起多个网络请求并等待它们的结果。
  • launch适合对任务完成后无需直接处理结果的场景,如不计返回值的操作。
    在协程使用中,选择合适的构建器依据实际需求,如执行主线上下文切换、需要并发结果处理或者单纯启动并行任务。通过理解withContext、async和launch的区别,可以更有效地设计异步任务的执行逻辑。

二、为何说 withContext是顺序执行

在Kotlin的协程中,说withContext是顺序执行的,是因为它的执行模型以及在协程中的角色使得它与其上下文中的代码保持了执行的顺序性。以下几点阐述了这种顺序执行特性:

1. 挂起协程但不创建新协程

不创建并发任务:与async不同,withContext并不会启动一个新的协程,而是挂起当前正在执行的协程,然后在指定的协程上下文中继续执行。在withContext完成之前,协程会被挂起。
立即执行并返回结果:当代码调用withContext时,程序流会直接切换到新上下文中执行指定代码块,执行完成后返回最后一个表达式的结果。在这一过程中,代码流是线性的。

2. 顺序流程的保证

线性逻辑顺序:withContext调用是阻塞当前协程的——注意,这是一种挂起执行,不是传统意义上的线程阻塞——这意味着在withContext代码块结束之前,后续代码不会被执行。这保证了执行顺序与代码编写顺序一致。
协程的挂起和恢复流程:因为协程在挂起时释放了线程,其它协程任务可以在该线程上执行,但对当前协程来说,它会等待withContext中任务的完成,并从那里继续执行后续的代码。

3. 用例场景的体现

在业务逻辑中,withContext设计用于在不同的上下文中处理顺序性任务,而不是用于引入并行或并发的复杂性。例如:

import kotlinx.coroutines.*fun main() = runBlocking {println("Main thread: ${Thread.currentThread().name}")val result = withContext(Dispatchers.IO) {println("Inside withContext, thread: ${Thread.currentThread().name}")performIoOperation()}println("Back to main thread, result: $result")
}suspend fun performIoOperation(): String {delay(1000L)  // 模拟IO操作return "IO Result"
}

在此代码中:

println(“Main thread: ${Thread.currentThread().name}”)在主线程中执行。
当withContext被调用时,当前协程被挂起,指定代码在IO上下文中执行。
一旦withContext完成,控制权返回到协程,它再继续执行后面的代码println(“Back to main thread, result: $result”)。

结论

因此,使用withContext时,虽然它可以修改协程所执行的上下文(比如切到其它线程),它在逻辑上是顺序执行的,确保其内的操作完成后才能继续后续执行。这种顺序性使其非常适合在协程中处理需要在指定调度器上完成的同步操作。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux TCP 之 RTT 采集与 RTO 计算

我们来看看 Linux TCP 采集 RTT 的函数 tcp_rtt_estimator&#xff0c;看注释&#xff0c;充满了胶着。 但在那个谨慎的年代&#xff0c;这些意味着什么&#xff1f; RTT 最初仅用于 RTO 的计算而不是用于调速&#xff0c;RTO 的计算存在两个问题&#xff0c;如果过估&#x…

如何使用CRM数据分析优化销售和客户关系?

嘿&#xff0c;大家好&#xff01;你有没有想过为什么有些公司在市场上如鱼得水&#xff0c;而另一些却在苦苦挣扎&#xff1f;答案可能就藏在他们的销售策略和客户关系管理&#xff08;CRM&#xff09;系统里。今天我们要聊的就是如何通过有效的 CRM 数据分析来提升你的销售额…

《Effective Java》学习笔记——第2部分 对象通用方法最佳实践

文章目录 第2部分 所有对象通用方法一、前言二、最佳实践内容1. equals()方法2. hashCode()方法3. toString() 方法4. clone() 方法5. finalize() 方法6. compareTo()方法&#xff08;实现 Comparable 接口&#xff09; 三、小结 第2部分 所有对象通用方法 一、前言 《Effect…

前沿技术趋势洞察:2024年技术的崭新篇章与未来走向!

引言 时光飞逝&#xff0c;2024年已经来临&#xff0c;回顾过去一年&#xff0c;科技的迅猛进步简直让人目不暇接。 在人工智能&#xff08;AI&#xff09;越来越强大的今天&#xff0c;我们不再停留在幻想阶段&#xff0c;量子计算的雏形开始展示它的无穷潜力&#xff0c;Web …

图的基本概念

一、图 二、顶点的度 三、图的同构 ​​​​​​​​​​​ 四、完全图 五、子图 六、补图

【游戏设计原理】75 - 最小最大化

一、理解与分析 最小/最大化的核心是玩家在角色扮演类游戏中使用的一种策略&#xff0c;旨在通过把角色的某些不利特性最小化、而有利特性最大化来增强角色在特定领域的优势。这种策略通常表现为以下几种形式&#xff1a; 角色单一化&#xff1a;玩家通过极端优化角色的某一项…

【K8S系列】K8s 领域深度剖析:年度技术、工具与实战总结

引言 Kubernetes作为容器编排领域的行业标准&#xff0c;在过去一年里持续进化&#xff0c;深刻推动着云原生应用开发与部署模式的革新。本文我将深入总结在使用K8s特定技术领域的进展&#xff0c;分享在过去一年中相关技术工具及平台的使用体会&#xff0c;并展示基于K8s的技术…

PyCharm+RobotFramework框架实现UDS自动化测试- (四)项目实战0x10

1.环境搭建 硬件环境&#xff1a;CANoe、待测设备&#xff08;包含UDS诊断模块&#xff09; 2.pythonPyCharm环境 pip install robotframework pip install robotframework-ride pip install openpyxl pip install udsoncan pip install python-can pip install can-isotp3…

mybatis(19/134)

大致了解了一下工具类&#xff0c;自己手敲了一边&#xff0c;java的封装还是真的省去了很多麻烦&#xff0c;封装成一个工具类就可以不用写很多重复的步骤&#xff0c;一个工厂对应一个数据库一个environment就好了。 mybatis中调用sql中的delete占位符里面需要有字符&#xf…

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证7)

本文验证基于请求头中传递token信息的认证方式&#xff0c;webapi项目的控制器类中新建如下函数&#xff0c;仅通过验证的客户端能调用&#xff0c;需要客户端请求在Header中添加’Authorization’: Bearer token’的键值对且通过token验证后才能调用。 [Authorize] [HttpGet]…

Linux:进程(三)

1. 进程创建补充 fork之后父子两个执行流分别执行&#xff0c;fork之后谁谁先执行由调度器来决定。 一般&#xff0c;父子代码共享。当父子不再写入时&#xff0c;数据也是共享的&#xff0c;但是当有一方要写入&#xff0c;就触发写时拷贝。 fork调用失败的原因 1. 系统中有…

一、vue智能Ai对话(高仿通义千问)普通版。

如需源码&#xff1a;请私信。 普通版视频地址&#xff1a;普通版视频 流式进阶版视频地址&#xff1a;流式进阶版视频 流式进阶版&#xff1a;流式进阶版源码 html结构和js方法&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta …

Taro+Vue实现图片裁剪组件

cropper-image-taro-vue3 组件库 介绍 cropper-image-taro-vue3 是一个基于 Vue 3 和 Taro 开发的裁剪工具组件&#xff0c;支持图片裁剪、裁剪框拖动、缩放和输出裁剪后的图片。该组件适用于 Vue 3 和 Taro 环境&#xff0c;可以在网页、小程序等平台中使用。 源码 https:…

【winRAR】windows11右键直接打开winRAR

总览 目前能够完成的操作不能像 win10 那样全面&#xff0c;需要做一些取舍&#xff0c;这两种解决后的样子任选其一&#xff1a; 1.右键之后&#xff0c;直接显示 “解压到当前文件夹” 2.右键之后&#xff0c;直接出现 winRAR 的母菜单&#xff0c;在鼠标 hover 到上面的时…

云计算、AI与国产化浪潮下DBA职业之路风云变幻,如何谋破局启新途?

引言 在近日举办的一场「云和恩墨大讲堂」直播栏目中&#xff0c;云和恩墨联合创始人李轶楠、副总经理熊军和欧冶云商数据库首席薛晓刚共同探讨了DBA的现状与未来发展。三位专家从云计算、人工智能、国产化替代等多个角度进行了深入的分析和探讨&#xff0c;为从业者提供了宝贵…

STM32 FreeRTOS 任务挂起和恢复---实验

实验目标 学会vTaskSuspend( )、vTaskResume( ) 任务挂起与恢复相关API函数使用&#xff1a; start_task:用来创建其他的三个任务。 task1&#xff1a;实现LED1每500ms闪烁一次。 task2&#xff1a;实现LED2每500ms闪烁一次。 task3&#xff1a;判断按键按下逻辑&#xff0c;KE…

2025年PHP面试宝典,技术总结。

面试是进入职场的第一道坎&#xff0c;因为我本身学校太一般的问题在面试中遇到了各种不爽&#xff0c;和那些高学历的相比自己真是信心大跌。我面试的方向是php开发工程师&#xff0c;主要做网站后台、APP接口等。下面是我这段时间总结的面试方面的常考常问的知识点&#xff0…

Python运算符

1、算术运算符 加 减— 乘* 除/ 整除// 取余% 幂运算** 优先级&#xff1a; 第1级&#xff1a;** 第2级&#xff1a;* &#xff0c; / &#xff0c; % &#xff0c;// 第3级&#xff1b; &#xff0c; - print("加", 1 4) print("减",8 - 19) p…

RTMP|RTSP播放器只解码视频关键帧功能探讨

技术背景 我们在做RTMP|RTSP直播播放器的时候&#xff0c;遇到过这样的技术诉求&#xff0c;在一些特定的应用场景中&#xff0c;可能只需要关键帧的信息&#xff0c;例如视频内容分析系统&#xff0c;可能只对关键帧进行分析&#xff0c;以提取特征、检测对象或场景变化。鉴于…

2024年度总结-CSDN

2024年CSDN年度总结 Author&#xff1a;OnceDay Date&#xff1a;2025年1月21日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 文章目录 2024年CSDN年度总结1. 整体回顾2…