kotlin - 为什么'await'阻塞了kotlin中的线程?
问题描述
'await' 的 api 描述:
在不阻塞线程的情况下等待该值的完成,并在延迟计算完成时恢复,返回结果值或如果延迟被取消则抛出相应的异常。
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 所说的不同。
解决方案
它不一定会阻塞线程。从您传递给的 lambda 构建的协程的执行runBlocking { ... }
暂停,然后在结果准备好one.await()
后恢复。one
在此期间,执行协程的线程可以切换到执行另一个协程(如果有的话)。但这不是因为,通过调用runBlocking { ... }
,您明确指定要在当前单线程中运行协程,独占使用线程直到协程完成,因此当协程挂起并且没有其他协程时阻塞线程跑。
例如,如果您在函数中添加第二对async { ... }
+ ,则调用实际上将同时执行。await
testAsyncAwait
await
您还可以使用明确支持运行多个协同程序的不同调度程序运行此协同程序,并且您会看到one.await()
在这种情况下调用不会阻塞线程。
例如,您可以按如下方式运行:
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
请参阅语言参考中的这些部分:
推荐阅读
- javascript - 如何向现有 url 添加参数?...Django...Paginator
- c# - SQLHelper 类 - 插入/更新方法返回插入的 ID @@identity
- c - sizeof 运算符在 c 中显示错误的结构大小
- arrays - 在 C 中迭代 MDA
- c# - 如何将相等过滤器应用于用户请求?
- json - 尝试使用 Play Json 添加 json 解析时“无法访问”隐式 val
- ruby-on-rails - 如何在会话中存储和使用多个 cart_id
- git - git add 没有添加整个代码库,代码现在被覆盖
- php - 当日期时间列<现在如何更新MySQL列/行?
- heroku - Heroku 上的 Celery beat(Redbeat):日志未显示