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

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意味着什么? 意味着你以后如果要装新的包的话&#xf…...

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主要用于多数传感器数据的读写&#xff0c…...

【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.从指定字符(子字符串)开…...

Java on VS Code 2月更新|JUnit 5 并行测试与 Spring Boot 插件的过滤功能

作者:Nick Zhu - Senior Program Manager, Developer Division at Microsoft 排版:Alan Wang 大家好,欢迎来到我们的二月更新!在此博客中,我们将为您带来与 JUnit 5 并行测试相关的新功能以及用于 Spring Boot Dashboa…...

无线WiFi安全渗透与攻防(三)之Windows扫描wifi和破解WiFi密码

系列文章 无线WiFi安全渗透与攻防(一)之无线安全环境搭建 无线WiFi安全渗透与攻防(二)之打造专属字典 windows下wifi进行扫描和破解 1.wifi扫描 (1).软件介绍 WirelessMon是一款无线网络扫描工具,它可以帮助用户扫描附近的无线信号&…...

Python中的遍历字典的键和值

一、Python的字典在项目的开发过程中,如果遇到有映射关系的内容可以考虑使用Python中的字典进行存储数据,字典中冒号前的数据称为【键】、冒号后的数据称为【值】。二、Python字典的用法2.1、Python的定义#Python字典的定义 字典名称{键1:值1,键2:值2,键…...

三天Golang快速入门—结构体

Struct结构体什么是结构体结构体定义基本实例化new实例化键值对初始化结构体方法和接收者结构体说明结构体方法和接收者值类型和指针类型接收者struct与jsonstruct转json字符串json转structstruct tagTag结构体转化Json字符串Json字符串转成Tag结构体什么是结构体 1.Golang中没…...

日常算法刷题——力扣704

##2023/3/2 刷算法的第一天 针对力扣的704题:本题是二分查找的基本使用!在此需要注意二分查找的基本特点: 1.数列基本有序; 2.数列数据内容不可重复。 此题只需了解二分查找算法的基本概念,无坑可跳。但在力扣上刷题就…...

【服务器数据恢复】VMware虚拟机下的SQL Server数据库数据恢复案例

服务器数据恢复环境: 一台某品牌PowerEdge系列服务器和一台PowerVault系列存储,上层是ESXI虚拟机文件,虚拟机中运行SQL Server数据库。 服务器故障: 机房非正常断电导致虚拟机无法启动。管理员检查虚拟机发现虚拟机配置文件丢失&…...

详解旨在提升EVM底层性能的兼容公链Monad

EVM带来的繁荣2020年以太坊链上DeFi的蓬勃发展使得EVM成为关注焦点,大部分DeFi项目都开始基于以太坊公链,这也使得EVM成为行业的标杆,不少链都加入了EVM大军,比如polygon、BSC、fantom等等,而EVM也使得链上生态进一步繁…...

2023社会工作者证书怎么考 在哪里报名考试

考取社会工作者证需要在网上报名,社工证是证书考试,分为初级、中级和高级三个级别,一般情况下满足报考条件就可以进行报考了,在中国人事考试网上进行报名及缴费。 1考取社会工作者证的流程 1、社工证报名需要登录中国人事考试网&a…...

统计学 类别比变量的判断

文章目录类别比变量的判断一个类别变量的拟合优度检验两个类别变量的独立性检验列联表与 χ2\chi^2χ2 独立性检验应用 χ2\chi^2χ2 检验应该注意的问题两个类别变量的相关度检验φ\varphiφ 系数Cramers VVV 系数列联系数总结类别比变量的判断 一个类别变量的拟合优度检验 …...

2.基于Label studio的训练数据标注指南:(智能文档)文档抽取任务、PDF、表格、图片抽取标注等

文档抽取任务Label Studio使用指南 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等 2.基于Label studio的训练数据标注指南:(智能文档)文档抽取任务、PDF、表格、图片抽取标注等…...

手机网站用什么做/如何快速推广网上国网

1. 日期转换的问题 问题提出: 下面的代码在运行时,由于 SimpleDateFormat 不是线程安全的,有很大几率出现 java.lang.NumberFormatException 或者出现不正确的日期解析结果,例如: Slf4j(topic "c.Test1") public clas…...

不用js可以做网站吗/合肥seo招聘

系列文章目录 Java管理扩展JMX入门学习 Spring JMX编程学习(一)- 手动注册bean到MBeanServer Spring JMX编程学习(二)- 以Bean的方式注册MbeanServer Spring JMX编程学习(三)- 自定义JMX客户端 Spring JMX…...

做任务给佣金的网站/亚马逊查关键词排名工具

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id1856 题意:有n个1和m个0组成的串,使得任意前k个中1的个数不少于0的个数。有多少种这样的串? 思路:设1为向(1,1)方向走,0为向(1,-1)方向走。那么…...

沙井做网站/发外链比较好的平台

一.命令行模式安装图形界面 检查已安装的组   yum grouplist 或者 yum grouplist | more 分页查看安装Gnone   yum groupinstall "GNOME Desktop" 语言设置 localectl status #查看当前语言 locale #查看当前域 localectl list-locales|grep CN #查看当前可用汉…...

免费网站后台管理系统html/seo网站优化专员

​​在Hadoop生态圈中,针对大数据进行批量计算时,通常需要一个或者多个MapReduce作业来完成,但这种批量计算方式是满足不了对实时性要求高的场景。 Storm是一个开源分布式实时计算系统,它可以实时可靠地处理流数据。 Storm特点 在…...

网站策划建设方法/seo与sem的区别

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼顺便大佬帮看下代码,是不是代码写的太笨拙了,跟语言没关系import java.util.Scanner;import java.util.Queue;import java.util.LinkedList;public class Main{private static int[][][] maze;private stati…...