'await' 的 api 描述:
Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete, returning the resulting value or throwing the corresponding exception if the deferred was cancelled.
fun main() = runBlocking {
val one = async { doSomethingUsefulOne() }
println("start->" + System.currentTimeMillis() / 1000)
one.await()
println("end->" + System.currentTimeMillis() / 1000)
}
suspend fun doSomethingUsefulOne(): Int {
delay(3000L)
return 13
}
结果:
开始-> 1575977567
结束->1575977570
'start' 和 'end' 之间有 3 秒的间隔。所以这行 'one.await()' 阻塞了线程。为什么它与 api 所说的不同。
最佳答案
它不一定会阻塞线程。从您传递给 runBlocking { ... }
的 lambda 构建的协程的执行暂停在 one.await()
然后恢复一次 one
结果准备好了。在此期间,执行协程的线程可以切换到执行另一个协程(如果有的话)。但这不是因为,通过调用 runBlocking { ... }
,您明确指定要在当前单线程中运行协程,独占使用线程直到协程完成,因此当协程挂起并且没有其他协程运行时阻塞线程。
例如,如果您添加第二对 async { ... }
+ await
在 testAsyncAwait
函数,await
调用实际上将同时执行。
您也可以使用明确支持运行多个协同程序的不同调度程序来运行此协同程序,您会看到 one.await()
在这种情况下, call 不会阻塞线程。
例如,您可以按如下方式运行:
suspend fun doSomethingUsefulOne(): Int {
delay(3000L)
return 13
}
suspend fun testAsyncAwait(n: Int) = coroutineScope {
val one = async { doSomethingUsefulOne() }
println("start $n ->" + System.currentTimeMillis() / 1000)
one.await()
println("end $n ->" + System.currentTimeMillis() / 1000)
}
suspend fun main() = coroutineScope {
val context = newSingleThreadContext("MyOwnThread")
repeat(2) {
launch(context) { testAsyncAwait(it) }
}
}
这两个协程将同时运行,
one.await()
不应阻塞单个线程:start 0 -> 1575982105
start 1 -> 1575982106
end 0 -> 1575982109
end 1 -> 1575982109
请参阅语言引用中的这些部分:
关于kotlin - 为什么 'await' 会阻塞 kotlin 中的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59266719/