通过Kotlin协程介绍(一)我们了解到协程可以让顺序的代码实现CPS的效果,实际上协程的本质就是在编译期将顺序代码变为CPS。协程用suspend关键字声明一个挂起函数
suspend fun delay(time: Int)
挂起函数经过编译后,在jvm里会变成一个CPS:
//Continuation用来实现CPS的回调
interface Continuation<T> {
void resumeWith(Result<T> result)
}
void delay(Int time, Continuation<Int> continuation)
delay通过continuation.resumeWith回调执行后续代码。挂起函数编译生成的CPS,不是一个简单的回调,而是一个状态机模型:
suspend fun simpleCoroutine() {
val start = System.currentTimeMillis()
println("start")
delay(1000) // 挂起点
println("end ${System.currentTimeMillis() - start}")
}
上面的代码编译器变为一个状态机:
class SimpleCoroutine {
var label = 0
var start = 0L
fun resume() {
when (label) {
0 -> {
start = System.currentTimeMillis()
println(“start")
label++
delay(1000, this)
}
1 -> {
println("end ${System.currentTimeMillis() - start}”)
label++
}
}
}
}
label代表当前状态,每一个挂起点和初始挂起点对应的 Continuation 都会转化为一种状态。随着挂起点的增加,只会增加状态,但不会增加回调嵌套的深度。挂起函数将执行过程分为多个 Continuation 片段,并且利用状态机的方式保证各个片段是顺序执行的。