Ste*_*erl 2 kotlin kotlin-coroutines
我正在尝试用 Kotlin 协程来理解异步代码执行。
为什么在启动异步代码块时必须指定调度程序?
以下代码块
fun doInParallel(): Unit = runBlocking {
coroutineScope {
launch { println("start A").also { Thread.sleep(1_000) }.also { println("finish A") } }
launch { println("start B").also { Thread.sleep(1_000) }.also { println("finish B") } }
}
}
Run Code Online (Sandbox Code Playgroud)
总是会打印
start A
finish A
start B
finish B
Run Code Online (Sandbox Code Playgroud)
这不是我所期望的。
仅在显式指定调度程序后,异步代码块才会并行运行:
fun doInParallel(): Unit = runBlocking {
coroutineScope {
launch(Dispatchers.Default) { println("start A").also { Thread.sleep(1_000) }.also { println("finish A") } }
launch(Dispatchers.Default) { println("start B").also { Thread.sleep(1_000) }.also { println("finish B") } }
}
}
Run Code Online (Sandbox Code Playgroud)
将打印
start A
start B
finish A
finish B
Run Code Online (Sandbox Code Playgroud)
为什么我必须包括Dispatcher.Default
?
我正在使用org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0-Beta
(如果有任何相关性的话)
而不是Thread.sleep(...)
使用delay(...)
.
Thread.sleep
阻塞线程,对于协程来说,你想要挂起线程,而不是阻塞它。当使用像这样的挂起函数从一个协程中挂起一个线程时delay
,同一个线程可以自由地为另一个协程提供服务——在本例中是由第二个协程启动的线程launch
。
在第二个示例中指定调度程序具有不同行为的原因是,它coroutineScope
从父作用域继承协程上下文,在本例中为runBlocking
. 协程构建器中的默认调度程序runBlocking
已记录:
此构建器的默认 CoroutineDispatcher 是事件循环的内部实现,它处理此阻塞线程中的延续,直到此协程完成。
换句话说,在您的示例中,所有内容都在单个线程内运行:主线程(或正在调用的任何线程doInParallel
)。与使用阻塞相结合Thread.sleep
意味着代码以阻塞方式同步执行。
总结一下:
更改代码以打印线程名称,您将看到所有内容都在main
线程中运行(除非您指定调度程序)。
从 using 更改Thread.sleep
为delay
修复根本问题,并允许单个线程运行两个启动的协程。
fun doInParallel(): Unit = runBlocking {
coroutineScope {
launch { println("${Thread.currentThread().name} start A").also { delay(1_000) }.also { println("${Thread.currentThread().name} finish A") } }
launch { println("${Thread.currentThread().name} start B").also { delay(1_000) }.also { println("${Thread.currentThread().name} finish B") } }
}
}
Run Code Online (Sandbox Code Playgroud)
要在协程内运行阻塞代码,请使用Dispatchers.IO
,它是专门为将阻塞任务卸载到共享线程池而设计的。此外,根据 @George Leung 的评论,runInterruptible
如果底层代码响应线程中断,则该方法可用于以可中断的方式调用指定的块。
归档时间: |
|
查看次数: |
455 次 |
最近记录: |