【发布时间】:2019-12-06 04:58:33
【问题描述】:
我已经尝试阅读有关 Kotlin 协程的各种教程和页面,尽管这对我来说有点道理,但我仍然觉得它没有被点击,我还没有准备好开始使用协程编写异步非阻塞代码.我认为我缺少的是一个图表或图片,说明一段协程代码执行时究竟发生了什么以及以什么顺序执行。该代码如何在线程级别运行?
launch {
delay(1000)
println("World (${currentThread().name})")
}
println("Hello (${currentThread().name})")
sleep(1500)
我的理解是这样的。我很高兴得到纠正或给出不同的例子来加深我的理解。
Line0:代码从主线程开始
Line1:在新线程上启动一个新的协程(我想来自 forkjoin 池)
Line2:挂起函数,协程挂起并将线程返回到线程池(因此是非阻塞的)
Line5:在主线程上打印
Line6:阻塞主线程1.5s
Line3:协程恢复执行(不确定这里的哪个线程 - 与挂起之前的线程相同还是可以是不同的线程?)。协程在该线程上打印并完成,因此再次将线程返回到池中。
我的另一个问题是,如果我将整个代码包装在 runBlocking { ... } 周围,低级执行将如何变化
【问题讨论】:
-
为了更好地了解背后的内容,我建议您观看此InfoQ presentation。它是关于 Oracle 正在进行的工作,旨在提供 Java 中的延续/纤程。从概念上讲,它很像 Kotlin 协同程序。
-
将“启动”视为 Java 中的传统线程创建会有所帮助,也就是说,它独立于创建它的主线程工作。
runBlocking表示协程及其创建的所有协程必须首先结束。应用于主程序,这意味着程序不会结束,除非所有生成的协程都完成(与守护程序不同)。 -
@Neil
runBlocking做的远不止这些,它为协程创建了一个运行环境。一旦你已经在协程环境中,甚至不应该使用它。它不会在协程完成之前结束,这只是一个副作用。 -
@MarkoTopolnik 我同意,但在一条评论中解释所有这些有点过分。我想将类似 java 的行为与 kotlin 中较新的协程区分开来,因为他可能来自 Java 背景。
-
@Neil 我明白你的意思。我仍然要指出
launch通常不会独立于创建它的主线程工作(Android 上的基本习惯是让它在同一个线程上工作),这几乎正是协程的原因与线程如此不同。你必须跳过这个认知圈,接受现在在单个线程上存在并发。这是真正挖掘协程的关键。
标签: asynchronous kotlin async-await kotlin-coroutines