Android kotlin实战之协程suspend详解与使用
前言
Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同,async 与 await 在 Kotlin 中并不是关键字,甚至都不是标准库的一部分。此外,Kotlin 的 挂起函数 概念为异步操作提供了比 future 与 promise 更安全、更不易出错的抽象。
kotlinx.coroutines 是由 JetBrains 开发的功能丰富的协程库。它包含本指南中涵盖的很多启用高级协程的原语,包括 launch、 async 等等。
如需了解其他kotlin用法,可查看如下:
Android Kotlin实战之高阶使用泛型扩展协程懒加载详解_蜗牛、Z的博客-CSDN博客
Android kotlin在实战过程问题总结与开发技巧详解_kotlin 同步锁_蜗牛、Z的博客-CSDN博客
Kotlin语法详解与实践教程,区分JAVA以及如何闭坑_kotlin mapof可以嵌套 to_蜗牛、Z的博客-CSDN博客
什么是协程suspend
suspend的字面含义是暂停、挂起的意思。在kotlin中,代码执行到 suspend 函数的时候会『挂起』,并且这个『挂起』是非阻塞式的,它不会阻塞你当前的线程,挂起的定位: 暂时切走,稍后再切回来,和java的Thread.sleep()不一样,一个是阻塞,一个是等待,类似wait。
阻塞的基本原理一直占用CUP,不让出如果sleep,挂起的是将自己的cup时间让出去,等待重新分配。这样就很好理解了。用最直观的理解是一种异步操作
协程方法的调用
如果当前方法被suspend修饰了,如果不是通过runblock或者coroutines 库调用,那么调用链上的所有函数都要背suspend修饰
1.修饰方法
suspend fun main() {delay(1000)println("hello")
}
又因为我们在业务中,很难会获取到main方法,所以无法通过main方法在源头解决协程的调用
2.借助工具类
2.1同步方法runBlocking
runBlocking是阻塞调用,如果通过它来处理协程,那么只有当runBlocking的方法体中执行完,才会往下执行,会一直霸占cpu,直到运行完才会释放。
fun main() {runBlocking {delay(1000)println("hello---block")}println("hello")
}

2.2异步库kotlinx.coroutines
异步库的调用是先挂起线程代码,继续执行,等下面执行完才会又回到协程函数执行
fun main() {GlobalScope.launch { // 在后台启动一个新的协程并继续println("suspend start!") // 在延迟后打印输出delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)println("suspend end!") // 在延迟后打印输出}println("sleep start,") // 协程已在等待时主线程还在继续Thread.sleep(2000L) // 阻塞主线程 2 秒钟来保证 JVM 存活println("sleep end,") // 协程已在等待时主线程还在继续}

通过以上日志分析,协程提都不会被执行,被挂起了,先执行了下面的代码,遇到sleep函数,形成阻塞,协程又获取到cpu的时间,开始执行协程代码快,执行完,sleep阻塞完成又继续执行。
coroutines 库的使用
kotlinx.coroutines是填补了kotlin在Java中的缺失,也提供了异步处理协程的问题。
依赖库:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
使用
1、异步挂起协程
GlobalScope.launch { // 在后台启动一个新的协程并继续//协程代码调用处}
2、延迟
GlobalScope.launch { // 在后台启动一个新的协程并继续delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)}
直接调用delay,设置需要阻塞延迟的时间
3、工作对象Job
launch会返回一个对象Job,job就是当前的任务,如果你接受了这个Job,那么代码块将不会执行,需要你手动调用
fun main() {val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用delay(1000L)println("World!")}println("Hello,")runBlocking {job.join() // 等待直到子协程执行结束}}
job的join只能在阻塞方法中调用,或者suspend方法体,不能在
GlobalScope.launch {job.join()
}
调用,否则不会执行当前代码块。因为launch已返回了一个job,当前job没有执行,所以,改job一直处于一个未执行状态。
也可以取消:job.cancel()
协程作用域:launch{}
GlobalScope与CoroutineScope对比
八股文显示,前者比后者快,通过源码分析,GlobalScope是继承了CoroutineScope,是对CoroutineScope的封装,提供一个静态函数。
结构化的并发
协程的实际使用还有一些需要改进的地方。 当我们使用 GlobalScope.launch 时,我们会创建一个顶层协程。虽然它很轻量,但它运行时仍会消耗一些内存资源。有一个更好的解决办法。我们可以在代码中使用结构化并发。 我们可以在执行操作所在的指定作用域内启动协程, 而不是像通常使用线程(线程总是全局的)那样在 GlobalScope 中启动.
fun main() = runBlocking { // this: CoroutineScopelaunch { // 在 runBlocking 作用域中启动一个新协程delay(1000L)println("World!")}println("Hello,")}
作用域构建器
除了由不同的构建器提供协程作用域之外,还可以使用 coroutineScope 构建器声明自己的作用域。它会创建一个协程作用域并且在所有已启动子协程执行完毕之前不会结束.
runBlocking 与 coroutineScope 可能看起来很类似,因为它们都会等待其协程体以及所有子协程结束。 主要区别在于,runBlocking 方法会阻塞当前线程来等待, 而 coroutineScope 只是挂起,会释放底层线程用于其他用途。 由于存在这点差异,runBlocking 是常规函数,而 coroutineScope 是挂起函数
fun main() = runBlocking { // this: CoroutineScopelaunch {delay(200L)println("Task from runBlocking 1")}coroutineScope { // 创建一个协程作用域launch {delay(500L)println("Task from nested launch 2")}delay(100L)println("Task from coroutine scope 3") // 这一行会在内嵌 launch 之前输出}println("Coroutine scope is over 4") // 这一行在内嵌 launch 执行完毕后才输出
}

挂起 :GlobalScope.async
GlobalScope的async异步挂起,支持返回值,且不能单独直接使用,需在runBlocking体内执行。
fun main()= runBlocking {println("current thread 1")//launch启动后台调度线程,并且不堵塞当前线程val deferred = GlobalScope.async {println("async thread 2=")delay(1000)println("async end 3")//需要通过标签的方式返回return@async "123"}println("current thread end 4")val result = deferred.await()println("result 5= $result")//当前线程休眠以便调度线程有机会执行Thread.sleep(3000)
}
协程上下文与调度器
协程上下文包含一个 协程调度器 (参见 CoroutineDispatcher)它确定了相关的协程在哪个线程或哪些线程上执行。协程调度器可以将协程限制在一个特定的线程执行,或将它分派到一个线程池,亦或是让它不受限地运行。
launch { // 运行在父协程的上下文中,即 runBlocking 主协程println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) { // 不受限的——将工作在主线程中println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) { // 将会获取默认调度器println("Default : I'm working in thread ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyOwnThread")) { // 将使它获得一个新的线程println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}
调度器类型如下:
public actual object Dispatchers {@JvmStaticpublic actual val Default: CoroutineDispatcher = DefaultScheduler@JvmStaticpublic actual val Main: MainCoroutineDispatcher get() = MainDispatcherLoader.dispatcher@JvmStaticpublic actual val Unconfined: CoroutineDispatcher = kotlinx.coroutines.Unconfined@JvmStaticpublic val IO: CoroutineDispatcher = DefaultIoScheduler@DelicateCoroutinesApipublic fun shutdown() {DefaultExecutor.shutdown()// Also shuts down Dispatchers.IODefaultScheduler.shutdown()}
}
调试协程与线程
协程可以在一个线程上挂起并在其它线程上恢复。 如果没有特殊工具,甚至对于一个单线程的调度器也是难以弄清楚协程在何时何地正在做什么事情。
启动方式
| runBlocking | 创建新的协程,运行在当前线程上,所以会堵塞当前线程,直到协程体结束 |
| GlobalScope.launch | 启动一个新的线程,在新线程上创建运行协程,不堵塞当前线程 |
| GlobalScope.asyn | 启动一个新的线程,在新线程上创建运行协程,并且不堵塞当前线程,支持 通过await获取返回值 |
相关文章:
Android kotlin实战之协程suspend详解与使用
前言 Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同,async 与 await 在 Kotlin 中并不是关键字,甚至都不是标准库的一部分。此外,Kotlin 的 挂起函数 概念为异步操作提供…...
Pycharm中的Virtualenv Environment、Conda Environment
版本一 Conda Environment该不该选? 先说结论,该选,而且还是正解。前提是你打算"用Anaconda来管理各种Python环境,同时管理Python下面的各种包"。 选了Conda Environment意味着什么? 意味着你以后如果要装新的包的话…...
C++容器介绍:vector
目录vector简介使用方法1.头文件2.vector声明及初始化3.vector基本操作(1). 容量(2). 修改(3)迭代器(4)元素的访问(5)算法vector 简介 vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vecto…...
抗锯齿和走样(笔记)
Artifacts(瑕疵): 比如人眼采样频率跟不上陀螺的旋转速度,这时就有可能看到陀螺在反方向旋转怎么做抗锯齿(滤波): 在采样之前先进行一个模糊操作,可以降低锯齿的明显程度 通过傅里叶…...
线程池的使用——线程池的创建方式
线程池的使用——创建线程线程池的创建线程池的创建方式Executors.newFixedThreadPool:Executors.newCachedThreadPool:Executors.newSingleThreadExecutor:Executors.newScheduledThreadPool:Executors.newSingleThreadScheduled…...
代码随想录算法训练营day47 |动态规划 198打家劫舍 213打家劫舍II 337打家劫舍III
day47198.打家劫舍1.确定dp数组(dp table)以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组213.打家劫舍II情况一:考虑不包含首尾元素情况二:考虑包含首元素,不包含尾元素情况三&#x…...
项目设计模式和规范
1、责任链模式 自己的理解:避免发生方与接收方解耦 优点:①降低发送方与接收方的耦合 ②简化他们对象 ③方便扩展新增 处理者 缺点:①不方便排错 ②性能问题,且使用不当容易搞出死循环 应用场景:拦截器 Interceptor和过滤器 filter:符合模式的进行拦截或者过滤到,然…...
无线WiFi安全渗透与攻防(一)之无线安全环境搭建
无线安全环境搭建 1.802.11标准 (1).概念 802.11标准是1997年IEEE最初制定的一个WLAN标准,工作在2.4GHz开放频段,支持1Mbit/s和2Mbit/s的数据传输速率,定义了物理层和MAC层规范,允许无线局域网及无线设备…...
【matplotlib】可视化解决方案——如何解决matplotlib中文乱码问题
问题概述 Matplotlib 默认不支持中文字体,这是因为 matplotlib 只支持 ASCII 字符,但是国人使用 matplotlib 肯定需要中文标注。如下图所示,当不对 Matplotlib 进行设置,而直接使用中文时,绘制的图像会出现中文乱码。…...
JAVA开发中GC日志打印简单通用的配置详解
如何配置一个完美的JVM日志打印信息 打印内容 打印基本的GC信息 打印对象分布情况 GC后打印堆数据 打印STW时间 打印safepoint信息 打印Reference处理信息 综上所述,最终的参数如下: 还有哪些问题呢?是不是有文件输出更好? 打印日…...
十进制的小数如何转二进制?二进制表示的小数如何转十进制?
😄 基础不牢,地动山摇~ 补补基础~ 文章目录 1、十进制的小数转二进制?2、二进制表示的小数转十进制?3、做道coding题巩固下:1、十进制的小数转二进制? 整数部分: 用普通的二进制表示即可。小数部分: 首先,将小数部分乘以2,取出整数部分作为二进制表示的第1位;然后…...
klipper使用webcam设置多个摄像头方式
一、前言 使用klipper设置多个摄像头,折腾了好些天,网上资料很少,这里写一个帖子记录一下 二、环境 参考链接:https://www.cnblogs.com/sjqlwy/p/klipper_webcam.html 我的klipper安装在香橙派上面,系统是debian&a…...
风力发电机组浪涌保护器安全防护方案
风机的庞大与危险高空作业注定了其在基建和维护中不易操作,风机设备的主电源、过程控制、网络与通讯、现场设备需要高等级的防雷浪涌保护器冲击保护,提高系统及设备的可靠性和可用性。风电场的主要发电设备风力发电机组“大风车”是风电场的主要发电设备…...
【剑指offer】JZ7 重建二叉树、JZ9 用两个栈实现队列
\描述: 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。 思路: 题上给了我们前序遍历(根 …...
ElasticSearch - SpringBoot整合ES之查询所有 match_all
文章目录1. 数据准备2. 全量查询 match_all3. 使用 boost 参数更改 _score官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/index.html权威指南:https://www.elastic.co/guide/cn/elasticsearch/guide/current/structured-search…...
详谈IIC
前言 在嵌入式底层系统中,常见的通讯方式,串口,IIC,SPI,IIS等,一般IIC,SPI,IIS更多的采取IO模拟,其余CAN,UART均是硬件设计直接支持,而IIC主要用于多数传感器数据的读写,…...
【Autoware】采集实验数据bag包并仿真运行
文章目录1. 官方demo包2. 控制底层地图采集3. 感知定位4. 规划控制5. 仿真或实车运行1. 官方demo包 wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_data.tar.gz wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_150324.tar.gz官方示例包的网上…...
名创优品怎么把创意做成生意?
最近,“主”无处不在,从让“依托答辩”梗火出圈的动画《三体》,到备受好评的电视剧《三体》,再到仍在刷新高票房成绩的《流浪地球2》。作为近些年来中国为数不多的爆款IP制造者,刘慈欣在《三体》中提出了一个著名的理论…...
springboot原项目配置文件迁移至nacos
目录一、配置文件迁移nacos1.安装nacos2.添加依赖3.改造service-product3.改造server-gateway一、配置文件迁移nacos 1.安装nacos 1,如果之前安装过nacos,nacos数据保存至mysql,先删除已安装的nacos,再安装 docker stop nacos …...
常用的shell脚步操作
文章目录一、如何开始一个shell脚本?1.基本语法2.变量定义规则二、特色变量1.$n2.$?三、条件判断1.基本语法2.运算符if,for,while四、字符串切割1.从指定位置开始截取从字符串左边开始计数从右边开始计数2.从指定字符(子字符串)开…...
保姆级教程:用MoveIt Setup Assistant配置你的第一个机械臂模型(ROS Noetic + Sunday机械臂)
MoveIt配置全指南:从机械臂模型到运动规划实战 刚接触ROS和机械臂开发时,最令人头疼的莫过于如何让机械臂"动起来"。MoveIt作为ROS生态中最强大的运动规划框架,其配置过程却常常让新手望而生畏。本文将带你一步步完成Sunday机械臂的…...
BepInEx插件框架:新手问题全解析与实战解决方案
BepInEx插件框架:新手问题全解析与实战解决方案 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 一、游戏启动异常:四步定位与修复方案 问题定位 当BepInE…...
Toggle库:嵌入式按钮消抖与事件驱动状态机框架
1. Toggle库:面向嵌入式系统的高性能按钮消抖与状态机抽象框架在嵌入式系统开发中,机械开关的物理抖动(bounce)是硬件与软件协同设计中最基础却最易被低估的挑战之一。一个看似简单的按键操作,在毫秒级时间尺度上可能产…...
YOLO12模型在C++环境下的高效调用与优化
YOLO12模型在C环境下的高效调用与优化 1. 引言 目标检测是计算机视觉领域的核心任务之一,而YOLO系列模型一直是这个领域的佼佼者。最新发布的YOLO12引入了以注意力为中心的架构,在保持实时推理速度的同时显著提升了检测精度。对于需要在C环境中部署高性…...
考虑通过控制分布式微发电机的无功功率注入来调节电力配电网的电压配置问题研究【IEEE56节点】(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
手把手教你部署通义千问WebUI:从环境配置到一键启动完整指南
手把手教你部署通义千问WebUI:从环境配置到一键启动完整指南 1. 项目概述与准备工作 通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI是基于阿里云通义千问团队推出的轻量级对话模型的网页交互界面。这个经过GPTQ-Int4量化的版本特别适合在消费级GPU或边缘设备上运行&…...
Unity 应用动态化交付新思路:Shiply 插件化解决方案深度解析
Unity 应用动态化交付新思路:Shiply 插件化解决方案深度解析一、Unity 应用更新面临的几个问题使用 Unity 引擎的团队——无论是游戏开发者还是构建 3D 交互应用的团队——普遍会遇到以下困境:场景一:紧急 Bug 修复线上突发崩溃或渲染异常&am…...
CHORD-X视觉战术指挥系统数据库课程设计参考:战术信息管理系统
CHORD-X视觉战术指挥系统数据库课程设计参考:战术信息管理系统 1. 项目背景与目标 如果你正在为数据库课程设计寻找一个既有技术深度又有实际应用价值的项目,那么这个基于“CHORD-X视觉战术指挥系统”的战术信息管理系统,或许能给你带来不少…...
粒子群算法求解IEEE 33节点最优潮流模型
粒子群算法求解 IEEE 33bus最优潮流模型关键词:粒子群算法 PSO 最优潮流 牛顿迭代 仿真平台:MATLAB 主要内容:这是一个用粒子群来解IEEE 33的最优潮流模型,潮流模型是用牛顿迭代法写的 模型包含了柴油机,储能ÿ…...
DeepSeek-OCR-2惊艳效果:91.09%准确率真实测试展示
DeepSeek-OCR-2惊艳效果:91.09%准确率真实测试展示 1. 突破性的OCR识别技术 DeepSeek-OCR-2代表了当前OCR技术的最前沿水平。这款由DeepSeek团队开发的第二代光学字符识别模型,在2026年1月发布后立即引起了广泛关注。它最引人注目的特点是在OmniDocBen…...
