Kotlin协程实现分析
- 协程的创建与启动
- 协程调度器都有哪些,分别表示什么含义
- delay既然是IO异步任务,是怎么做到延迟协程的代码向下执行的
- suspend关键字的作用
- 并发流程控制 async await
- 协程挂起与恢复原理逆向剖析
- 如何让一个普通函数成为一个挂起函数,即让调用方以一个同步的方式拿到调用结果
协程的创建与启动
1 | GlobalScope.launch(Dispatchers.Unconfined) { |
启动一个协程可以使用launch
或 async
1 | public fun CoroutineScope.launch( |
CoroutineContext
可以理解为协程的上下文,是一种key-value数据结构
CoroutineStart
协程启动模式
模式 | 说明 |
---|---|
CoroutineStart.DEFAULT | 默认模式,创建即启动,可随时取消 |
CoroutineStart.LAZY | 延迟启动模式,只有调用start方法才能启动 |
CoroutineStart.ATOMIC | 自动模式,创建即启动,启动前不可取消 |
协程调度器
模式 | 说明 |
---|---|
Dispatcher.IO | 指定协程运行的线程为IO线程 |
Dispatcher.Main | 指定协程运行的线程为主线程 |
Dispatcher.Default | 默认的,启动协程时会启动一个线程 |
Dispatcher.Undefined | 不指定,就是在当前线程执行,协程恢复后运行的线程取决于挂起时的线程 |
协程挂起与恢复原理
挂起就是这个协程从当前执行他的线程上脱离。
- 协程挂起的本质: 就是方法的挂起return
- 协程恢复的本质: callback的回调(Continution)
挂起函数
1 | suspend fun request1(): String { |
将协程suspend方法通过反编译成Java代码
1 | //1. 被标记为suspend的函数会被编译器自动添加 Continuation 参数,实现类是ContinuationImpl |
看DelayKt.delay 的返回值得时候,需要找到DelayKt的class文件并反编译成java源码
1 | // DelayKt.java |
看下协程时怎么改变方法的状态的
1 | internal fun getResult(): Any? { |
图示
协程的应用
如何让一个普通函数成为一个挂起函数,即让调用方以一个同步的方式拿到调用结果
读取assets目录下的文件
以同步的形式拿到返回值
suspendCancellableCoroutine
1 | object CoroutineScene3 { |
以同步的方式调用
1 | val content = CoroutineScene3.parseAssetsFile(assets, "config.json") |
小结
- kotlin协程的核心是线程的挂起和恢复,挂起和恢复的核心是 return - callback
- suspend本质就是一个提醒,在反编译成java代码后会添加一个回调Continuation
- 协程的非阻塞挂起实质上是以非阻塞式的形式写出了阻塞式的代码
- 让一个普通函数成为一个挂起函数