Kotlin协程中awaitAll()的行为差异及串行执行原因探究
协程作用域位置对执行效率的影响
预热后执行两个函数的结果差异明显:
good():7msbad():618ms
核心原因解析
要理解这个差异,关键在于coroutineScope的特性:它是一个挂起函数,会等待其内部所有子协程执行完毕后,自身才会结束挂起。
good()的并行执行逻辑
在good()中,repeat(100)循环被包裹在同一个coroutineScope内部:
- 循环的100次迭代中,每次调用
async都会在这个共享的作用域下启动一个子协程 - 这些子协程会被调度器并行执行,各自的
delay(5)不会互相阻塞 coroutineScope会等待这100个协程全部完成,总耗时只接近单个delay(5)的时间(加上少量调度开销,因此是7ms左右)
bad()的串行执行逻辑
在bad()中,repeat(100)循环在coroutineScope外部,每次迭代都会创建一个新的coroutineScope:
- 第一次循环创建的
coroutineScope内部启动一个async协程,coroutineScope必须等这个协程的delay(5)执行完才会结束 - 只有当前一个
coroutineScope结束后,才会进入下一次循环,创建新的作用域和协程 - 相当于100个协程依次串行执行,总耗时是
5ms * 100加上调度开销,最终达到618ms左右
完整代码
suspend fun good() = buildList { coroutineScope { // 在coroutineScope内部循环 repeat(100) { add(async { delay(5) }) } } }.awaitAll() suspend fun bad() = buildList { // 在coroutineScope外部循环 repeat(100) { coroutineScope { add(async { delay(5) }) } } }.awaitAll() suspend fun main() { // 预热操作 measureTimeMillis { good() } .also { println("good: ${it}ms") } measureTimeMillis { bad() } .also { println("bad: ${it}ms") } }
内容的提问来源于stack exchange,提问作者JasonMing
相关产品推荐
相关产品推荐

