转载请标明出处:https://www.cnblogs.com/tangZH/p/16849169.html

-[kotlin协程小记]
-[协程的async使用]
- [kotlin协程异常处理之-try catch ]
- [kotlin协程异常处理之-CoroutineExceptionHandler]

例子一:

GlobalScope.launch(Dispatchers.Main) {
//开启子协程
withContext(Dispatchers.IO) {
for (i in 0 until 1000) {
}
Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

打印log:

2022-10-09 20:24:21.100 8371-8371/com.example.xiecheng D/MainActivityXX: onCreate-> thread:main
2022-10-09 20:24:21.131 8371-8412/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-10-09 20:24:21.258 8371-8371/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main

例子二:

GlobalScope.launch(Dispatchers.Main) {
//开启子协程
withContext(Dispatchers.IO) {
for (i in 0 until 1000) {
}
Log.d("MainActivityXX", "withContext1-> thread:" + Thread.currentThread().name)
withContext(Dispatchers.IO) {
for (i in 0 until 1000) {
}
Log.d("MainActivityXX", "withContext2-> thread:" + Thread.currentThread().name)
}
}
withContext(Dispatchers.IO) {
for (i in 0 until 1000) {
}
Log.d("MainActivityXX", "withContext3-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

打印log:

onCreate-> thread:main
withContext1-> thread:DefaultDispatcher-worker-1
withContext2-> thread:DefaultDispatcher-worker-1
withContext3-> thread:DefaultDispatcher-worker-1
GlobalScope-> thread:main

主线程开启一个协程,并不会阻碍主线程的执行,单个协程内部是串行执行的,这里整一个都是串行执行的是因为withContext是一个挂起函数。

GlobalScope.launch(Dispatchers.Main) {
//开启子协程
GlobalScope.launch (Dispatchers.IO) {
Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}

打印log:

GlobalScope-> thread:main
withContext-> thread:DefaultDispatcher-worker-1

例子二:

GlobalScope.launch(Dispatchers.Main) {
//开启子协程
withContext(Dispatchers.IO) {
get()
Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
suspend fun get() {
Thread {
Thread.sleep(5000)
Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}.start()
}
 

打印log:

2022-11-01 20:56:25.220 20058-20100/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-11-01 20:56:25.264 20058-20058/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main
2022-11-01 20:56:30.222 20058-20103/com.example.xiecheng D/MainActivityXX: get-> thread:Thread-8

协程里面开启线程,那么线程不会受协程影响。

例子三:

GlobalScope.launch(Dispatchers.Main) {
fetchDocs()
} suspend fun fetchDocs() { // Dispatchers.Main
val result = get("https://developer.android.com") // Dispatchers.IO for `get`
Log.d("MainActivityXX", "fetchDocs-> thread:" + Thread.currentThread().name)
}
//withContext本身就是挂起函数
suspend fun get(url: String) = withContext (Dispatchers.IO) {
Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}

打印log:

get-> thread:DefaultDispatcher-worker-1
fetchDocs-> thread:main

使用了挂起函数,会先等待get方法执行完再执行下面得操作。

1、挂起函数并不会阻塞其所在线程,这样就极大地提高了线程的并发灵活度,最大化了线程的利用效率。
当在 ThreadA 上运行的 CoroutineA 调用了delay(1000L)函数指定延迟一秒后再运行,ThreadA 会转而去执行 CoroutineB,等到一秒后再来继续执行 CoroutineA

2、withContext本身就是挂起函数。

3、挂起的对象是协程。

4、这个 suspend 关键字,既然它并不是真正实现挂起,它其实是一个提醒。函数的创建者对函数的使用者的提醒:我是一个耗时函数,我被我的创建者用挂起的方式放在后台运行,所以请在协程里调用我。
为什么 suspend 关键字并没有实际去操作挂起,但 Kotlin 却把它提供出来?
因为它本来就不是用来操作挂起的。挂起的操作 —— 也就是切线程,依赖的是挂起函数里面的实际代码,而不是这个关键字。
所以这个关键字,只是一个提醒。
所以,创建一个 suspend 函数,为了让它包含真正挂起的逻辑,要在它内部直接或间接调用 Kotlin 自带的 suspend 函数,你的这个 suspend 才是有意义的。

5、所以这个 suspend,其实并不是起到把任何把协程挂起,或者说切换线程的作用。真正挂起协程这件事,是 Kotlin 的协程框架帮我们做的。
所以我们想要自己写一个挂起函数,仅仅只加上 suspend 关键字是不行的,还需要函数内部直接或间接地调用到 Kotlin 协程框架自带的 suspend 函数才行。

6、开发者需要明白,协程是运行于线程上的,一个线程可以运行多个(可以是几千上万个)协程。线程的调度行为是由 OS 来操纵的,而协程的调度行为是可以由开发者来指定并由编译器来实现的。当协程 A 调用 delay(1000L) 函数来指定延迟1秒后再运行时,协程 A 所在的线程只是会转而去执行协程 B,等到1秒后再把协程 A 加入到可调度队列里。所以说,线程并不会因为协程的延时而阻塞,这样可以极大地提高线程的并发灵活度。

kotlin协程小记的更多相关文章

  1. Kotlin协程第一个示例剖析及Kotlin线程使用技巧

    Kotlin协程第一个示例剖析: 上一次https://www.cnblogs.com/webor2006/p/11712521.html已经对Kotlin中的协程有了理论化的了解了,这次则用代码来直 ...

  2. Retrofit使用Kotlin协程发送请求

    Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...

  3. Kotlin协程基础

    开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...

  4. Android Kotlin协程入门

    Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...

  5. Kotlin 协程一 —— 全面了解 Kotlin 协程

    一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...

  6. rxjava回调地狱-kotlin协程来帮忙

    本文探讨的是在tomcat服务端接口编程中, 异步servlet场景下( 参考我另外一个文章),用rxjava来改造接口为全流程异步方式 好处不用说 tomcat的worker线程利用率大幅提高,接口 ...

  7. Kotlin协程解析系列(上):协程调度与挂起

    vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...

  8. Kotlin协程通信机制: Channel

    Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间 ...

  9. Kotlin协程作用域与Job详解

    Job详解: 在上一次https://www.cnblogs.com/webor2006/p/11725866.html中抛出了一个问题: 所以咱们将delay去掉,需要改造一下,先把主线程的dela ...

  10. Kotlin协程作用域与构建器详解

    在上次我们是通过了这种方式来创建了一个协程: 接着再来看另一种创建协程的方式: 下面用它来实现上一次程序一样的效果,先来回顾一下上一次程序的代码: 好,下面改用runBlocking的方式: 运行一下 ...

随机推荐

  1. 【JS 逆向百例】猿人学系列 web 比赛第二题:js 混淆 - 动态 cookie,详细剖析

    逆向目标 猿人学 - 反混淆刷题平台 Web 第二题:js 混淆,动态 cookie 目标:提取全部 5 页发布日热度的值,计算所有值的加和 主页:https://match.yuanrenxue.c ...

  2. (数据科学学习手札113)Python+Dash快速web应用开发——表单控件篇(下)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 由我开源的先进Dash组件库feffery-antd-co ...

  3. 快速上手NPM包管理

    NPM官网 前提 安装nodejs 检测安装成功的命令 node -v 显示版本号即为安装成功 快速上手教程 第一步注册NPM账号官网在上面 第二步骤随便找个地方新建一个文件夹 然后这个文件夹我们用C ...

  4. 从零开始配置 vim(11)——插件管理

    之前我们介绍了基础配置部分和快捷键配置部分.如果你配置了这两个部分,vim已经算是比较好用了.但是作为代码编辑器来讲还是显的比较简陋,用这些配置来完成日常的编码任务会显得力不从心.vim比较强大的一点 ...

  5. C/C++ 反汇编:分析类的实现原理

    反汇编即把目标二进制机器码转为汇编代码的过程,该技术常用于软件破解.外挂技术.病毒分析.逆向工程.软件汉化等领域,学习和理解反汇编对软件调试.系统漏洞挖掘.内核原理及理解高级语言代码都有相当大的帮助, ...

  6. centos环境下MySQL8.0.25离线升级至8.0.32

    环境 centos7 mysql8.0.25 下载新版本mysql 下载地址:https://dev.mysql.com/downloads/mysql/ 升级 备份数据 先保存原始数据,进入mysq ...

  7. PHP的无限极分类

    PHP的无限极分类 一.使用数据表 添加from字段 id name parent_id from 1 中国 0 0 2 广东 1 0,1 3 深圳 2 0,1,2 4 龙华 3 0,1,2,3 5 ...

  8. git~issue在github/gitlab中的使用

    本文档适用于github和gitlab issue介绍 GitHub 中的 issue 功能是一种用于跟踪项目中任务.缺陷.功能请求和讨论的工具.通过 issue,项目成员可以提出问题.报告 bug. ...

  9. C语言输出百分号%

    遭遇的问题 在学习时有一个课后题要求计算两个变量的加减乘除以及取余,其中去余需要输出如下的效果: 10 % 5 = 0; 我就写了这样的代码: printf("a % b = %d" ...

  10. 案例:OGG目标端进程ABENDED处理

    源端环境:RHEL 6.5 + Oracle 11.2.0.4 RAC + OGG 19.1.0.0.4 目标端环境:RHEL 7.6 + Oracle 19.3 + OGG 19.1.0.0.4 故 ...