协程 Coroutine 到底是个啥?

news2024/11/13 10:22:08

看了很多博客,也看了些在线课堂的课程。大神们说的协程 Coroutine 的概念,一直含糊不清。今天自己动手做做实验理解下。

1. 代码如下

private const val i1 = 1000000000

class MainViewModel : ViewModel() {
    companion object {
        private const val TAG = "MainViewModel"
    }

    suspend fun getData() {
        Trace.beginSection("getData");
        Log.e(TAG, "getData before " + Thread.currentThread().name)
        viewModelScope.launch(Dispatchers.IO) {
            Trace.beginSection("DispatchersIO");
            Log.e(TAG, "getData IO 1  " + Thread.currentThread().name)
            Thread.sleep(1000)
            Log.e(TAG, "getData IO 2 " + Thread.currentThread().name)
            Trace.endSection();
        }
        viewModelScope.launch(Dispatchers.Default) {
            Trace.beginSection("DispatchersDefault");
            Log.e(TAG, "getData Default 1  " + Thread.currentThread().name)
            Thread.sleep(1000)
            Log.e(TAG, "getData Default 2 " + Thread.currentThread().name)
            Trace.endSection();
        }
        viewModelScope.launch(Dispatchers.Unconfined) {
            Trace.beginSection("DispatchersUnconfined");
            Log.e(TAG, "getData Unconfined 1  " + Thread.currentThread().name)
            dealJob()
            Trace.beginSection("DispatchersUnconfined-");
            delay(1000)
            Thread.sleep(1000 * 5)
            Trace.endSection();
            Log.e(TAG, "getData Unconfined 2 " + Thread.currentThread().name)
            Trace.endSection();
        }
        viewModelScope.launch(Dispatchers.Main) {
            Log.e(TAG, "getData Main 1  " + Thread.currentThread().name)
            Trace.beginSection("DispatchersMain");
            dealJob()
            Trace.beginSection("DispatchersMain-");
            Thread.sleep(1000)
            Log.e(TAG, "getData Main 2 " + Thread.currentThread().name)
            Trace.endSection();
            Trace.endSection();
        }
        withContext(Dispatchers.IO) {
            Trace.beginSection("withContext");
            Thread.sleep(1000 * 20)
            Trace.endSection();
        }

        Trace.beginSection("lastLog");
        dealJob()
        Trace.endSection();
        Trace.endSection();
        Log.e(TAG, "getData end " + Thread.currentThread().name)
    }

    private fun dealJob() {
        var rr = 0L;
        for (i in 0..i1) {
            rr += (i % 10)
        }
    }
}

2. 通过代码 system trace 文件,观察线程切换

见资源:ltrace.html 

3. 输出 log

10-11 20:41:04.801 21917 26304 E MainViewModel: getData before DefaultDispatcher-worker-1
10-11 20:41:04.802 21917 26306 E MainViewModel: getData IO 1  DefaultDispatcher-worker-3
10-11 20:41:04.802 21917 26305 E MainViewModel: getData Default 1  DefaultDispatcher-worker-2
10-11 20:41:04.803 21917 26304 E MainViewModel: getData Unconfined 1  DefaultDispatcher-worker-1
10-11 20:41:05.803 21917 26306 E MainViewModel: getData IO 2 DefaultDispatcher-worker-3
10-11 20:41:05.803 21917 26305 E MainViewModel: getData Default 2 DefaultDispatcher-worker-2
10-11 20:41:11.123 21917 26304 E MainViewModel: getData Unconfined 2 DefaultDispatcher-worker-1
10-11 20:41:11.125 21917 21917 E MainViewModel: getData Main 1  main
10-11 20:41:12.633 21917 26197 I Quality : stackInfo :----- pid 21917 at 2023-10-11 20:41:12.626 -----;Cmd line: com.haier.uhome.coroutine;"main" prio=5 tid=2 TIMED_WAITING sysTid=21917;  at java.lang.Thread.sleep(Native Method);  at java.lang.Thread.sleep(Thread.java:450);  at java.lang.Thread.sleep(Thread.java:355);  at com.haier.uhome.coroutine.ui.main.MainViewModel$getData$5.invokeSuspend(MainViewModel.kt:50);  at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33);  at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106);  at android.os.Handler.handleCallback(Handler.java:942);  at android.os.Handler.dispatchMessage(Handler.java:99);  at android.os.Looper.loopOnce(Looper.java:240);  at android.os.Looper.loop(Looper.java:351);  at android.app.ActivityThread.main(ActivityThread.java:8427);  at java.lang.reflect.Method.invoke(Native Method);  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584);  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013);
10-11 20:41:13.451 21917 21917 E MainViewModel: getData Main 2 main
10-11 20:41:32.439 21917 26304 E MainViewModel: getData end DefaultDispatcher-worker-1

4. trace 部分截图

问:协程到底是什么?

答:协程就是对线程的一次封装。协程把线程的切换逻辑封装到 suspend 下的 launch 方法里。以顺序的代码流程执行线程的切换操作。如以上 log 里第 2 行、第 5 行,IO 相关的执行完再执行第 8 行的 Main 线程的逻辑。符合人的思维逻辑。

问:协程中非主线程的工作,会创建线程吗?

答:就像上边 log 和 trace 文件所示。协程并不是完全不做线程创建和切换,子线程 26304,26305,26848 等子线程依然是创建了的。

问:使用协程会提升性能吗?

答:从红框里可以看到,代码 26 行到 34 行,和 46 行到 50 行内容在同一个线程执行。说明协程对线程进行了有效的复用。减少线程的创建和销毁,当然能提升性能

问:在执行协程内部非主线程的内容时,主线程在干什么?是如果实现主线程不耗时等待导致 anr 的?

答:从主线程的状态可以看到,执行非主线程的内容时,主线程在 sleep,释放了 cpu 才不会有主线程的 anr 计时,也就不会导致 anr。

见资源:trace.html 

如图所示,子线程 30960 会在合适的位置唤醒包括主线程在内的其他线程,达到了线程切换,顺序执行,又不会 block 导致 anr 的目的。

5. 团队介绍

「三翼鸟数字化技术平台-场景设计交互平台」主要负责设计工具的研发,包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力,研发并沉淀素材库,构建家居家装素材库,集成户型库、全品类产品库、设计方案库、生产工艺模型,打造基于户型和风格的AI设计能力,快速生成算量和报价;同时研发了门店设计师中心和项目中心,包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理,同时为水,空气,厨房等产业提供商机管理工具,从而实现了以场景贯穿的B端C端全流程系统。

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

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

相关文章

MySQL数据库基础第一篇(SQL通用语法与分类)

文章目录 一、SQL通用语法二、SQL分类三、DDL语句四、DML语句1.案例代码2.读出结果 五、DQL语句1.DQL-基本查询2.DQL-条件查询3.DQL-聚合函数4.DQL-分组查询5.DQL-排序查询6.DQL-分页查询7.DQL语句-执行顺序1.案例代码2.读出结果 六、DCL语句1.DCL-管理用户2.DCL-权限控制1.案例…

C++ 数论相关题目:容斥原理。能被整除的数

给定一个整数 n 和 m 个不同的质数 p1,p2,…,pm 。 请你求出 1∼n 中能被 p1,p2,…,pm 中的至少一个数整除的整数有多少个。 输入格式 第一行包含整数 n 和 m 。 第二行包含 m 个质数。 输出格式 输出一个整数,表示满足条件的整数的个数。 数据范围 1≤m≤16 ,…

中移(苏州)软件技术有限公司面试问题与解答(5)—— Linux进程调度参数调优是如何通过代码实际完成的1

接前一篇文章:中移(苏州)软件技术有限公司面试问题与解答(0)—— 面试感悟与问题记录 本文对于中移(苏州)软件技术有限公司面试问题中的“(11)Linux进程调度参数调优是如…

python-自动化篇-办公-文件-加解密

解说 要使⽤Python进⾏⽂件的加密和解密,可以使⽤第三⽅加密库,如cryptography或pycryptodome。 ⼀个基本的⽰例,演⽰如何使⽤cryptography库对⽂件进⾏加密和解密: 安装cryptography库: pip install cryptography⽂…

docker中三种常用的持久化数据的方式

文章目录 介绍1.docker run -v2.volumes3.bind mounts 介绍 “前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。” 在Docker中,有以下三种常用的持久化数据的方式,可…

AI智能分析+明厨亮灶智慧管理平台助力“舌尖上的安全”

春节是中国最重要的传统节日之一,在春节期间,人们聚餐需求激增,餐饮业也迎来了高峰期。在这个时期,餐饮企业需要更加注重食品安全和卫生质量,以保证消费者的健康和权益,明厨亮灶智慧管理成为了餐饮业中备受…

代码随想录刷题第21天

第一题是二叉搜索树的最小绝对差,初始思路是中序遍历将二叉搜索树转换为有序数组,在有序数组中进行遍历。一遍过了。(手机打代码真的麻烦)看卡哥讲解会了双指针法遍历。 第二题是二叉搜索树中的众数,还是只想到了中序…

基于spring boot实现邮箱发送和邮箱验证

目录 一、邮箱发送实现1. 开通邮箱服务2. 添加邮箱依赖3.添加配置4.添加邮箱通用类5. 测试类 二、邮箱验证实现1.添加依赖2. 添加配置3.添加controller4. 测试 项目地址: https://gitee.com/nssnail/springboot-email 一、邮箱发送实现 1. 开通邮箱服务 使用qq邮箱、163邮箱都…

1月无代码资讯 | 两项低代码无代码行业报告相继重磅发布;GitHub Copilot Chat全面开放使用

栏目导读:无代码资讯栏目从全球视角出发,带您了解无代码相关最新资讯。 TOP3 大事件 1、ResearchAndMarkets.com "低代码无代码开发平台市场—— 2018-2028 年全球行业规模、份额、趋势、机遇及预测"报告发布 据雅虎财经近日资讯显示&#xf…

推荐一个可以采集众多国内外电商网站数据的API接口【附请求代码】

目前专门针对各大电商平台的数据分析工具很多,也支持数据导出。如针对亚马逊的helium10和junglescout等。 但这些工具对于需要随时跨平台采集数据是无能为力的。 这时,你需要一个万能的采集工具(也就是通用的爬虫工具)。 本文推…

whistle 抓包工具使用

安装配置whistle,本机环境是win10 1、whistle 安装,首先电脑上需要安装node.js,然后就可以使用npm命令安装whistle: npm install -g whistle 2、安装完后就可以使用whistle命令了: 启动:w2 start 重启&#…

分布式搜索引擎_学习笔记_2

分布式搜索引擎_学习笔记_2 在昨天的学习中,我们已经导入了大量数据到elasticsearch中,实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天,我们研究下elasticsearch的数据搜索功能。我们会分别使用…

数据库空间爆了怎么处理

作者: 马文斌 时间: 2024-1-29 标签: mysql 磁盘空间 爆满 binlog 背景 近期数据库空间一直告警,平时这套数据库集群是不会有磁盘空间告警的,难道是最近业务量猛增了吗?咱们来瞧瞧到底怎么回事&…

springboot142新冠病毒密接者跟踪系统

新冠病毒密接者跟踪系统设计与实现 摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲&#xff…

故障诊断 | 一文解决,SVM支持向量机的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,SVM支持向量机的故障诊断(Matlab) 支持向量机(Support Vector Machine,SVM)是一种常用的监督学习算法,用于分类和回归分析。SVM的主要目标是找到一个最优的超平面(或者在非线性情况下是一个最优的超曲面),将不同类别的样本分开…

第二证券:沪指再度失守2800点,2月行情怎么走?

周三A股三大指数继续下行,上证指数再度失守2800点。 1月31日,沪深股指早盘小幅收拾后快速下行,盘中一度克复部分跌幅,但午后沪深股指再次回落。到收盘,沪指指数跌1.48%,深证成指跌1.95%,创业板…

Linux——安装MySQL

1、安装mysql8.0.35 1.1、安装步骤 1.更新包列表,首先,确保您的系统已更新到最新状态。运行以下命令来更新包列表和安装最新的软件包: sudo apt update sudo apt upgrade2.安装MySQL服务器:运行以下命令来安装MySQL服务器&…

windows 谷歌浏览器Chrome 怎么禁止更新

1.首先把任务管理器里的谷歌浏览器程序结束: (鼠标在任务栏右击,出现任务管理器) 2.windowr,输入services.msc 带有Google Update的服务,选择禁用。 3.windowr,输入taskschd.msc 任务计划程序…

蓝桥杯---牌型种数

小明被劫持到X赌城,被迫与其他3人玩牌。一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。这时,小明脑子里突然冒出一个问题:如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后…

《幻兽帕鲁》1月29日游戏服务器推荐!腾讯云降低规格再次降价!

腾讯29日刷新规格,从14M降低到12M,硬盘和流量都有降低,但价格打下来了!价格从66元/月降低到32元/月,277元/3个月降低到96元/3个月! 三大厂商4核16G的云服务器价格对齐,不过具体参数略有不同 阿里…