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

Kotlin 协程的挂起和阻塞的区别

一,简介

Kotlin协程引入了非常强大的异步编程模型,通过挂起而不是阻塞来实现并发操作。以下是有关Kotlin协程挂起和阻塞的详细介绍:

  1. 挂起(Suspending):
    • 挂起是指一个协程的执行可以在不阻塞线程的情况下暂停和恢复。
    • 挂起函数是一种能够让协程挂起并释放线程的特殊函数,允许其他协程在该协程挂起期间运行。
    • 协程可以在执行IO操作、等待网络请求、休眠或执行任何可能导致阻塞的操作时挂起。
  1. 阻塞:
    • 阻塞是指线程在执行某个操作时被暂停,直到该操作完成,而不能执行其他任务。
    • 在传统的多线程编程中,通常会使用阻塞调用(如Thread.sleep()或等待I/O操作完成),这会导致线程被阻塞,浪费了宝贵的资源。
  1. 协程的非阻塞特性:
    • Kotlin协程通过将任务挂起到后台线程而不阻塞主线程,使得在同一线程上执行多个任务变得更加高效。
    • 由于协程不需要一直占用线程,所以可以运行大量协程而无需创建太多线程。
  1. 使用协程挂起函数:

在Kotlin中,使用suspend关键字声明挂起函数,这允许函数在协程中挂起。

例如,suspend fun fetchData(): String是一个可以在协程中挂起的函数,它可以执行异步操作而不阻塞线程。

  1. 协程调度器:
  • 协程的执行受调度器的管理,调度器负责决定何时挂起和恢复协程,以及在哪个线程上运行它们。
  • 通过使用不同的调度器,可以控制协程的执行方式,例如在主线程、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()函数。

现在,让我们看看挂起和阻塞的区别:

  1. 挂起:在async中使用await()函数来获取网络请求的结果,但在等待网络请求的过程中,协程会挂起,而不会阻塞整个线程。这意味着其他协程可以在此期间运行,而不会浪费线程资源。
  2. 阻塞:如果我们使用传统的阻塞方式,例如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 协程的挂起和阻塞的区别

一&#xff0c;简介 Kotlin协程引入了非常强大的异步编程模型&#xff0c;通过挂起而不是阻塞来实现并发操作。以下是有关Kotlin协程挂起和阻塞的详细介绍&#xff1a; 挂起&#xff08;Suspending&#xff09;&#xff1a; 挂起是指一个协程的执行可以在不阻塞线程的情况下暂…...

解决Github Markdown图片显示残缺的问题

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

[MAUI]深入了解.NET MAUI Blazor与Vue的混合开发

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

1209. 带分数

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

【树莓派触摸屏等学习笔记】

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

ERR_PNPM_JSON_PARSE Unexpected end of JSON input while parsing empty string in

终端报错&#xff1a;  ERR_PNPM_JSON_PARSE  Unexpected end of JSON input while parsing empty string in   报错原因&#xff1a;依赖没有删除干净  解决办法&#xff1a;  ①删除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卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…...

LLMs之RAG:利用langchain实现RAG应用五大思路步骤—基于langchain使用LLMs(ChatGPT)构建一个问题回答文档的应用程序实战代码

LLMs之RAG:利用langchain实现RAG应用五大思路步骤—基于langchain使用LLMs(ChatGPT)构建一个问题回答文档的应用程序实战代码 目录 相关文章...

链式队列----数据结构

队列的基本概念 队列是一种操作受限的线性表&#xff08;先进先出&#xff09;&#xff0c;只允许在队尾插入&#xff0c;队头删除。 例如去银行办理业务&#xff0c;肯定是先来的先出去&#xff0c;后来的人排在后方&#xff0c;只有第一个人业务办理完了&#xff0c;才会有…...

VM虚拟机VMware Fusion(13.5.0)

VMware Fusion提供了在Apple Mac上运行Windows、Linux等操作系统的最佳方式&#xff0c;无需重新启动。Fusion 13支持运行macOS 12及更高版本的Intel和Apple Silicon Mac&#xff0c;并包含面向开发人员、IT管理员和日常用户的功能。 Fusion 13 新增功能 支持新的客户机操作系…...

自动化测试08

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

d3dx9_43.dll丢失有什么办法可以解决,解决d3dx9_43.dll丢失

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

【C++】: auto关键字(C++11)+基于范围的for循环(C++11)+指针空值nullptr(C++11)

auto关键字&#xff08;C11&#xff09; 随着程序越来越复杂&#xff0c;程序中用到的类型也越来越复杂&#xff0c;经常体现在&#xff1a; 类型难于拼写含义不明确导致容易出错 #include <string> #include <map> int main() {std::map<std::string, std::…...

华为OD机试 - 玩牌高手 - 动态规划(Java 2023 B卷 100分)

目录 一、题目描述二、输入描述三、输出描述四、解题思路具体规则如下&#xff1a;具体步骤如下&#xff1a; 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 一、题目描述 给定一个长度为n的整型数组&#xff0…...

【java】【重构二】分模块开发版本锁定以及耦合(打包)实战

目录 一、创建dependencyManagement标签 二、 将需要版本控制的依赖版本进行标签设置 三、将需要版本控制的依赖从各子模块迁移到此处 四、将父模块的依赖版本控制 五、删除子模块的全部版本 1、bocai-web-management模块 2、bocai-utils模块 六、打包 1、确定代码都…...

Excel提高工作效率常用功能

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

物联网_00_物理网介绍

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

华为智选SF5,AITO问界的车怎么样

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

大数据测试用例分析

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

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析

LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...