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}")}

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

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

相关文章

百分点科技再度亮相GITEX全球大会

10月16-20日&#xff0c;全球最大科技信息展会之一 GITEX Global 2023在迪拜世贸中心开展&#xff0c;本届展会是历年来最大的一届&#xff0c;吸引了来自180个国家的6,000家参展商和180,000名技术高管参会。 百分点科技作为华为生态合作伙伴&#xff0c;继去年之后再度参展&a…

Css 如何取消a链接点击时的背景颜色

要取消 <a> 链接点击时的背景颜色&#xff0c;可以使用 CSS 的伪类 :active。你可以通过为 a:active 应用 background-color 属性设置为 transparent 或者 none&#xff0c;来取消点击时的背景色。下面是一个示例&#xff1a; a:active {background-color: transparent;…

C++:类的默认成员函数------构造函数析构函数(超详细解析,小白一看就懂!)

目录 一、前言 二、为什么会出现构造函数和析构函数 三、构造函数 &#x1f34e;构造函数的概念 &#x1f350;构造函数特性 &#x1f4a6;解释特性3&#xff1a;对象实例化时编译器自动调用对应的构造函数 &#x1f4a6;解释特性4&#xff1a;构造函数支持重载 &…

平板有必要买触控笔吗?推荐的ipad手写笔

iPad之所以能吸引这么多人&#xff0c;主要是因为它的功能出色。用来画画、做笔记&#xff0c;也是一种不错的体验。但如果只是用来看电视和打游戏的话&#xff0c;那就真的有点大材小用了。如果你不需要昂贵的苹果电容笔&#xff0c;也不需要用来专业的绘图&#xff0c;那你可…

Oracle缓存表

Oracle缓存表&#xff08;db_buffer_pool&#xff09;由三部分组成&#xff1a; buffer_pool_defualt buffer_pool_keep buffer_pool_recycle 如果要把表钉死在内存中&#xff0c;也就是把表钉在keep区。相关的命令为&#xff1a; alter table 表名 storage(buffer_pool k…

Python高级篇(08):生成器

一、生成器定义和作用 定义&#xff1a;Python中&#xff0c;一边循环一边计算的机制作用&#xff1a;循环的过程中不断推算出后续的元素&#xff0c;这样就不必创建完整的list&#xff0c;从而节省大量的空间 二、生成器创建方法 1、简单生成器&#xff1a;将列表推导式的[…

经典题型---旋转数组

经典题型—旋转数组 文章目录 经典题型---旋转数组一、题目二、代码实现 一、题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步…

2021年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 下列代码的输出结果是&#xff1f;&#xff08; &#xff09; x 0x10print(x)A&#xff1a;2 B&#xff1a;8 C&#xff…

读《Gaitset: Regarding gait as a set for cross-view gait recognition》

2019在AAAI&#xff08;还有一版叫GaitSet: Regarding Gait as a Set for Cross-View Gait Recognition&#xff0c;大体上一样&#xff09; 摘要 现有的步态识别方法要么利用步态模板&#xff0c;难以保存时间信息&#xff0c;要么利用保持不必要的顺序约束的步态序列&#x…

免费Scrum管理工具-Leangoo领歌

Leangoo领歌是一款永久免费的专业的敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;涵盖敏捷需求管理、任务协同、进展跟踪、统计度量等。 
 Leangoo领歌上手快、实施成本低&#xff0c;可帮助企业快速落地敏捷&#xff0c;提质增效、缩短周期、加速…

MySQL -- 环境安装(CentOS7)

MySQL – 环境安装&#xff08;CentOS7&#xff09; 文章目录 MySQL -- 环境安装&#xff08;CentOS7&#xff09;一、环境安装1.卸载不必要的环境2.检查系统安装包3.卸载默认安装包4.获取MySQL官方yum源6.看看yum源能不能正常工作7.安装mysql服务 二、MySQL登录与配置1.启动My…

项目经理之识别项目干系人

项目干系人管理是项目管理中的重要一环&#xff0c;识别和管理好项目干系人是成功实施项目的关键之一。本文将介绍4321项目干系人识别方法、干系人等级册以及五步判断法等工具&#xff0c;帮助项目经理更好地识别和管理项目干系人。同时&#xff0c;本文还将介绍干系人能量方格…

智慧矿山矿山安全生产:皮带撕裂识别AI算法不用激光,能迅速识别皮带纵撕!

近些年来&#xff0c;智慧矿山在煤矿行业中发挥着越来越重要的作用。皮带的功能对于矿山运营至关重要&#xff0c;而皮带撕裂是造成生产中断、人身伤害等问题的重要原因之一。为了准确、及时地检测皮带撕裂的情况&#xff0c;AI算法的应用成为智慧矿山的关键。 ​​​​​​​…

软件报错msvcr120.dll丢失怎么办?五个有效修复方法分享

msvcr120.dll是一个动态链接库文件&#xff0c;它是Microsoft Visual C 2012 Redistributable Package的一部分。如果你的电脑在运行一些需要这个文件的程序时出现了“msvcr120.dll丢失”的错误&#xff0c;那么就意味着你的电脑缺少了这个文件&#xff0c;或者这个文件已经损坏…

GoogLeNet的不同版本

GoogLeNet 致敬 LeNet GoogLeNet V1 Inception块&#xff0c;增加网络宽度&#xff0c;在卷积操作时可以提取不同尺度特征利用11卷积进行降维&#xff0c;减少参数量参数量计算&#xff1a;上一层通道数 卷积层的长度^2 下一层通道数采用模块化结构Stage最后进行全局平均池…

从文心大模型4.0与FuncGPT:用AI为开发者打开新视界

今天&#xff0c;在百度2023世界大会上&#xff0c;文心大模型4.0正式发布&#xff0c;而在大洋的彼岸&#xff0c;因为大模型代表ChatGPT之类的AI编码工具来势汹汹&#xff0c;作为全世界每个开发者最爱的代码辅助网站&#xff0c;Stack Overflow的CEO Prashanth Chandrasekar…

3、Kafka Broker

4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 &#xff08;1&#xff09;启动 Zookeeper 客户端。 [hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh&#xff08;2&#xff09;通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2] ls /kaf…

Three.js + Tensorflow.js 构建实时人脸点云

本文重点介绍使用 Three.js 和 Tensorflow.js 实现实时人脸网格点云所需的步骤。 它假设你之前了解异步 javascript 和 Three.js 基础知识&#xff0c;因此不会涵盖基础知识。 该项目的源代码可以在此 Git 存储库中找到。 在阅读本文时查看该代码将会很有帮助&#xff0c;因为…

【实战】学习 Electron:构建跨平台桌面应用

文章目录 一、Electron 简介二、Electron 的优势1. 学习曲线平缓2. 丰富的生态系统3. 跨平台支持4. 开源和社区支持 三、Electron 的使用1. 安装 Node.js2. 安装 Electron3. 创建项目4. 初始化项目5. 安装依赖6. 创建主进程文件7. 创建渲染进程文件8. 打包应用程序9. 运行应用程…

【debug】安装diffusion的bug解决合集

环境问题 ImportError: cannot import name ‘CLIPImageProcessor’ from ‘transformers’ (D:\Python\lib\site-packages\transformers_init_.py) https://github.com/huggingface/transformers/issues/23340 解决&#xff1a;查看更详细信息&#xff0c;安装环境 transfor…