Kotlin 协程的挂起和阻塞的区别
一,简介
Kotlin协程引入了非常强大的异步编程模型,通过挂起而不是阻塞来实现并发操作。以下是有关Kotlin协程挂起和阻塞的详细介绍:
- 挂起(Suspending):
-
- 挂起是指一个协程的执行可以在不阻塞线程的情况下暂停和恢复。
- 挂起函数是一种能够让协程挂起并释放线程的特殊函数,允许其他协程在该协程挂起期间运行。
- 协程可以在执行IO操作、等待网络请求、休眠或执行任何可能导致阻塞的操作时挂起。
- 阻塞:
-
- 阻塞是指线程在执行某个操作时被暂停,直到该操作完成,而不能执行其他任务。
- 在传统的多线程编程中,通常会使用阻塞调用(如Thread.sleep()或等待I/O操作完成),这会导致线程被阻塞,浪费了宝贵的资源。
- 协程的非阻塞特性:
-
- Kotlin协程通过将任务挂起到后台线程而不阻塞主线程,使得在同一线程上执行多个任务变得更加高效。
- 由于协程不需要一直占用线程,所以可以运行大量协程而无需创建太多线程。
- 使用协程挂起函数:
在Kotlin中,使用suspend关键字声明挂起函数,这允许函数在协程中挂起。
例如,suspend fun fetchData(): String是一个可以在协程中挂起的函数,它可以执行异步操作而不阻塞线程。
- 协程调度器:
- 协程的执行受调度器的管理,调度器负责决定何时挂起和恢复协程,以及在哪个线程上运行它们。
- 通过使用不同的调度器,可以控制协程的执行方式,例如在主线程、IO线程或自定义线程池中执行。
总之,Kotlin协程的挂起机制允许在不阻塞线程的情况下执行异步任务,这在编写高效且响应式的并发代码方面非常有用。挂起函数使协程可以在等待I/O或执行其他可能导致阻塞的操作时,让出线程,以提高应用程序的性能和响应性。
二,示例
以下是使用Kotlin协程的示例,演示了挂起和阻塞的区别:
首先,确保你的项目中已经引入了Kotlin协程库,以便使用协程。
kotlinCopy codeimport kotlinx.coroutines.*
import kotlin.system.measureTimeMillis// 一个挂起函数,模拟网络请求
suspend fun fetchData(): String {delay(1000) // 模拟延迟1秒的网络请求return "Data from the network"
}fun main() = runBlocking {// 创建一个协程作用域val time = measureTimeMillis {val result = async { fetchData() } // 启动一个协程来执行网络请求println("Waiting for data...")println("Data received: ${result.await()}")}println("Time taken: $time ms")
}
上述代码中,我们创建了一个挂起函数fetchData(),它模拟了一个网络请求,使用delay()函数来模拟1秒的延迟。在main函数中,我们使用runBlocking创建了一个协程作用域,以便执行协程。然后,我们使用async启动一个协程来执行fetchData()函数。
现在,让我们看看挂起和阻塞的区别:
- 挂起:在async中使用await()函数来获取网络请求的结果,但在等待网络请求的过程中,协程会挂起,而不会阻塞整个线程。这意味着其他协程可以在此期间运行,而不会浪费线程资源。
- 阻塞:如果我们使用传统的阻塞方式,例如Thread.sleep(1000),线程将被完全阻塞,无法执行其他任务。这会浪费线程资源,并降低应用程序的性能。
总之,使用协程的挂起机制,可以实现非阻塞的并发操作,提高了应用程序的性能和资源利用率。而传统的阻塞方式则会浪费线程资源,导致应用程序的响应性下降。
三,通过Android项目展示挂起和阻塞的区别
在Android项目中演示挂起和阻塞更容易理解
我们之到通过 runBlocking创建一个顶层协程,会阻塞所在的线程;例如我们在主线程使用runBlocking创建一个需要耗时操作的协程;
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.ang.rxdemo1.databinding.ActivityCoroutine2Binding
import kotlinx.coroutines.*class CoroutineActivity2 : AppCompatActivity() {lateinit var binding: ActivityCoroutine2Binding;private var job: Job? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityCoroutine2Binding.inflate(layoutInflater)setContentView(binding.root)binding.btnSubmit.setOnClickListener {runBlocking(Dispatchers.IO + CoroutineName("顶层协程")) {//协程中有耗时操作,需要10S才能执行完成Log.d(TAG,"协程开始执行")delay(1000.times(10))Log.d(TAG,"协程执行完成")}}}
xml布局:activity_coroutine2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"tools:context=".xiecheng.CoroutineActivity"><Buttonandroid:id="@+id/btn_submit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="执行"/></androidx.appcompat.widget.LinearLayoutCompat>
测试连续多次点击”执行”按钮稍等片刻后就会出现ANR导致程序崩溃;这就是runBlocking创建的协程阻塞主线程无法执行其他操作,导致的用户无响应异常的出现;
如果上面代码使用协程挂起函数执行耗时操作,不会阻塞主线程的执行;
binding.btnSubmit.setOnClickListener {
// runBlocking(Dispatchers.IO + CoroutineName("顶层协程")) {//协程中有耗时操作,需要10S才能执行完成
// Log.d(TAG,"协程开始执行")
// delay(1000.times(10))
// Log.d(TAG,"协程执行完成")
// }val coroutineScope = CoroutineScope(Dispatchers.Main + CoroutineName("协程A"))coroutineScope.launch{Log.d(TAG,"协程开始执行 ${Thread.currentThread().name} ${coroutineContext[CoroutineName]?.name}")delay(10000)//挂起函数,挂起当前协程Log.d(TAG,"协程执行完成 ${Thread.currentThread().name} ${coroutineContext[CoroutineName]?.name}")}}
在多次点击不会阻塞主线,所以也不会出现ANR 异常;
也可以通过如下代码对比挂起和阻塞的区别
阻塞线程:
binding.btnSubmit.setOnClickListener {Thread.sleep(100000)Log.d(TAG,"协程执行完成 ${Thread.currentThread().name}")}
挂起非阻塞线程:
binding.btnSubmit.setOnClickListener {GlobalScope.launch(Dispatchers.Main + CoroutineName("协程A")) {Log.d(TAG,"协程开始执行 ${Thread.currentThread().name} ${coroutineContext[CoroutineName]?.name}")delay(10000)//挂起函数,挂起当前协程Log.d(TAG,"协程执行完成 ${Thread.currentThread().name} ${coroutineContext[CoroutineName]?.name}")}// Thread.sleep(100000)
// Log.d(TAG,"协程执行完成 ${Thread.currentThread().name}")}
相关文章:
Kotlin 协程的挂起和阻塞的区别
一,简介 Kotlin协程引入了非常强大的异步编程模型,通过挂起而不是阻塞来实现并发操作。以下是有关Kotlin协程挂起和阻塞的详细介绍: 挂起(Suspending): 挂起是指一个协程的执行可以在不阻塞线程的情况下暂…...

解决Github Markdown图片显示残缺的问题
title: 解决Github Markdown图片显示残缺的问题 tags: 个人成长 categories:杂谈 在Github存放Markdown文档,如果图片没有存放在Github服务器上,github会尝试生成Github图片缓存,使用Github图片缓存,进行实际的展示。但比较蛋疼的…...

[MAUI]深入了解.NET MAUI Blazor与Vue的混合开发
文章目录 Vue在混合开发中的特点创建MAUI项目创建Vue应用使用element-ui组件库JavaScript和原生代码的交互传递根组件参数从设备调用Javascript代码从Vue页面调用原生代码 读取设备信息项目地址 .NET MAUI结合Vue的混合开发可以使用更加熟悉的Vue的语法代替Blazor语法ÿ…...

1209. 带分数
题目: 1209. 带分数 - AcWing题库 思路: 1.targetab/c,由题意a,b,c会包含1~9 且每个数出现且只能出现一次。我们可以抽象化为9个坑位分成3份分别给a,b,c。 2.先采用递归搜索树写出9个坑位的全排列,再分成3个区,分…...

【树莓派触摸屏等学习笔记】
前言 树莓派触摸屏 提示:以下是本篇文章正文内容,下面案例可供参考 一、触摸屏硬件驱动 出现黑屏的时候,恢复一下txt config.txt 全屏显示 showFull Exec :自启动 surf 算法 特征点识别 算法的复杂度挺高的 特性树莓派强大…...

ERR_PNPM_JSON_PARSE Unexpected end of JSON input while parsing empty string in
终端报错: ERR_PNPM_JSON_PARSE Unexpected end of JSON input while parsing empty string in 报错原因:依赖没有删除干净 解决办法: ①删除node_modules ②在package.json的dependencies删除不需要依赖 ③重新pnpm i...

linux基础IO
文章目录 前言一、基础IO1、文件预备知识1.1 文件类的系统调用接口1.2 复习c语言接口 2、文件类的系统调用接口2.1 open系统调用2.2 close系统调用2.3 write系统调用2.4 read系统调用 3、文件描述符3.1 文件描述符fd介绍3.2 文件描述符fd分配规则与重定向3.3 重定向原理3.4输入…...

华为OD机试 - TLV格式 - 逻辑分析(Java 2023 B卷 100分)
目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…...
LLMs之RAG:利用langchain实现RAG应用五大思路步骤—基于langchain使用LLMs(ChatGPT)构建一个问题回答文档的应用程序实战代码
LLMs之RAG:利用langchain实现RAG应用五大思路步骤—基于langchain使用LLMs(ChatGPT)构建一个问题回答文档的应用程序实战代码 目录 相关文章...
链式队列----数据结构
队列的基本概念 队列是一种操作受限的线性表(先进先出),只允许在队尾插入,队头删除。 例如去银行办理业务,肯定是先来的先出去,后来的人排在后方,只有第一个人业务办理完了,才会有…...
VM虚拟机VMware Fusion(13.5.0)
VMware Fusion提供了在Apple Mac上运行Windows、Linux等操作系统的最佳方式,无需重新启动。Fusion 13支持运行macOS 12及更高版本的Intel和Apple Silicon Mac,并包含面向开发人员、IT管理员和日常用户的功能。 Fusion 13 新增功能 支持新的客户机操作系…...

自动化测试08
Junit 为什么学了Selenium还需学习Junit Selenium自动化测试框架;Junit单元测试框架。 拿着一个技术写自动化测试用例(Selenium3) 拿着一个技术管理已经编写好的测试用例(Junit5) Junit相关的技术 Junit是针对Java的一…...

d3dx9_43.dll丢失有什么办法可以解决,解决d3dx9_43.dll丢失
通常d3dx9_43.dll丢失都是在运行游戏时汤出的d3dx9_43.dll找不到的错误窗口,因为d3dx9_43.dll文件更多是在使用游戏时会被调用的dll文件,d3dx9_43.dll是属于DirectX9的一个组件,DirectX9是游戏系统中的一个重要程序,所以当d3dx9_4…...

【C++】: auto关键字(C++11)+基于范围的for循环(C++11)+指针空值nullptr(C++11)
auto关键字(C11) 随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在: 类型难于拼写含义不明确导致容易出错 #include <string> #include <map> int main() {std::map<std::string, std::…...

华为OD机试 - 玩牌高手 - 动态规划(Java 2023 B卷 100分)
目录 一、题目描述二、输入描述三、输出描述四、解题思路具体规则如下:具体步骤如下: 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 一、题目描述 给定一个长度为n的整型数组࿰…...

【java】【重构二】分模块开发版本锁定以及耦合(打包)实战
目录 一、创建dependencyManagement标签 二、 将需要版本控制的依赖版本进行标签设置 三、将需要版本控制的依赖从各子模块迁移到此处 四、将父模块的依赖版本控制 五、删除子模块的全部版本 1、bocai-web-management模块 2、bocai-utils模块 六、打包 1、确定代码都…...

Excel提高工作效率常用功能
定位快捷键使用 CtrlG或者F5 根据不同类别插入空行 例:以下表,以部门为单位,每个部门后插入空白行 部门姓名出勤基本工资岗位津贴公体加班绩效基数工龄应发合计财务部姓名73115002101710财务部姓名11116006003401502363财务部姓名5271000…...

物联网_00_物理网介绍
1.物联网为什么会出现? 一句话-----追求更高品质的生活, 随着科技大爆炸, 人类当然会越来越追求衣来伸手饭来张口的懒惰高品质生活, 最早的物联网设备可以追溯到19世纪末的"在线可乐售卖机"和"特洛伊咖啡壶"(懒惰的技术人员为了能够实时看到物品的情况而设…...

华为智选SF5,AITO问界的车怎么样
#华为智选 #赛力斯SF5 #aito问界m5 #aito问界m7 #华为汽车 华为的车,后杠焊两点,拉车的时候,拖车钩断了,后杠拉出来了,这质量可以吗?是否应该全部召回?M5,M7是不是也这样?…...

大数据测试用例分析
基于大数据分析,对业务系统产生的日志进行智能分析,能够识别日志中的接口、参数、业务流,并依据分析的结果生成测试用例。 问题与背景 业务复杂 业务系统的复杂性,对测试人员的业务能力提出严格要求,加重测试成本。 …...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
[QMT量化交易小白入门]-六十二、ETF轮动中简单的评分算法如何获取历史年化收益32.7%
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读1. 策略概述2. 趋势评分模块3 代码解析4 木头…...

《架构即未来》笔记
思维导图 第一部分:可扩展性组织的人员配置 第二部分:构建可扩展的过程 第三部分:可扩展的架构方案 第四部分:其他的问题和挑战 资料 问软件工程研究所: https://www.sei.cmu.edu/ AKF公司博客: http://www.akfpart…...