结论
先说结论 感想,状态机转变 在最后面。
- kotlin的suspend coroutines,为简化 异步代码 的书写,compiler处理异步回调。
- 程序员注明异步的method ,以 direct call形式编码
- compiler生成 回调,并以 状态机 调用
如视频所说,没有magic。类比于用 中文写程序,中文是宏命令啥的。(个人臆测)
我了解的点
- compiler帮你用 回调书写异步代码
- compiler将你的code,翻译成状态机,来运行、暂停你的代码 。
- 相当于用关键字 suspend、await 告诉compiler,我代码怎么拆分。然后compiler跟你拆成 一段一段的代码,来执行。
不足:
- 没 涉及 coroutines是如何调度的,具体啥线程。VM 的领域知识了吧。
推测
- 细化了异步调用粒度,到 method粒度(其实就是coroutines)
- 实际上Thread run方法,也是method粒度啊
- 算是扩充了 异步调用的方式吧
- Compiler 根据susepnd关键字,给你翻译成 一块一块的代码。
- 所谓程序 加个中间层,啥问题都解决了
- 所谓的non-suspend,确实是non-suspend。因为这套框架 一直在调度 语句块 (携程)。
感想
这尼玛确实不用深入理解,因为你Thread杂跑异步的,你不也没去理解嘛。。。。。。
这就是新手为啥好掌握吧,没有理解包袱。
资料
文章翻译的Google视频,本人也是听了个大概,故本文仅 抛砖引玉,难以深度解惑,诸君如有需要 还需自行看视频。 当然,各位如有指导、资料,更是期望不吝赐教,多谢。
笔记
你写的源码,为direct call,没有callback。但Compiler 会给你生成Callback,就这么简单。。。。。。。。
Compiler 转变的大致步骤:
//direct call
suspend fun postItem(item: Item) {
//suspend action
val token = requestToken()
//Continuation
val post = createPost(token, item)
procsessPost(post)
}
//indirect call CPS
fun postItem(item: Item) {
requestToken { token ->
createPost(token, item) { post ->
processPost(post)
}
}
}
//direct call
suspend fun postItem(item: Item) {
//Label 0
val token = requestToken()
//Label 1
val post = createPost(token, item)
//Label 2
procsessPost(post)
}
//direct call
suspend fun postItem(item: Item) {
switch (label) {
case 0:
val token = requestToken()
case 1:
val post = createPost(token, item)
case 2:
porcessPost(post)
}
}
// Save state
suspend fun postItem(item: Item, cont: Continuation) {
val sm = object: CoroutineImpl {...}
switch (sm.label) {
case 0:
//val token = requestToken(sm)
sm.item = item
sm.label = 1
requestToken(sm)
case 1:
val post = createPost(token, item, sm)
case 2:
porcessPost(post)
}
}
Compiler生成了一个Continuation,并添加到方法的形参中。而这个interface就是callback的抽象,并由Compiler根据 suspend等 关键字,抽取实际代码
interface Continuation<T> {
val context: CorotineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
// generate Callback
suspend fun postItem(item: Item, cont: Continuation) {
val sm = object: CoroutineImpl {
fun resume() {
postItem(null, this)
}
}
switch (sm.label) {
case 0:
//val token = requestToken(sm)
sm.item = item
sm.label = 1
requestToken(sm)
case 1
val item = sm.item
val token = sm.result as Token
sm.label = 2
val post = createPost(token, item, sm)
}
}
State Machine vs Callbacks
//State Machine
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
procsessPost(post)
}
//Callbacks
fun postItem(item: Item) {
requestToken { token ->
createPost(token, item) { post ->
processPost(post)
}
}
}
-
StateMachine分配类少
StateMachine:重用closure / state object (即对应Item)
Callback: 每次调用suspend function,都需要create new object (即对应的callback实参)) -
便于 处理N个异步请求
//State Machine
suspend fun postItem(items: Item) {
for (item in items) {
val token = requestToken()
val post = createPost(token, item)
procsessPost(post)
}
}
//Callbacks
fun postItem(item: Item) {
// 回调地狱
requestToken { token ->
createPost(token, item) { post ->
processPost(post)
requestToken { token ->
createPost(token, item) { post ->
processPost(post)
//....
}
}
}
}
}