为何添加delay后Kotlin协程未切换仍同步执行?
协程未异步执行的原因及修复方案
问题根源
你当前的代码里,runBlocking循环中每创建一个async协程就立刻调用await(),这会直接阻塞当前协程的执行流程——必须等这个async任务从头到尾跑完,才会继续循环创建下一个协程。相当于把本应异步的任务强制改成了串行执行,自然不会出现delay时的协程切换。
从你的执行日志也能验证这一点:每个链接都是"접근 완료"后立刻完成"파싱 완료",再启动下一个链接的任务,完全是同步顺序执行。
修复方案
要实现真正的并发,需要先批量启动所有async协程,最后统一等待所有任务完成,而不是启动一个等一个。修改后的runBlocking代码如下:
runBlocking { // 1. 先批量启动所有协程,将任务存入列表(此时所有协程同时开始执行) val jobList = bookLinks.mapIndexed { ranking, bookLink -> async { scrapeBookData(browser, bookLink, ranking) } } // 2. 等待所有协程执行完毕,收集所有结果 val results = jobList.awaitAll() // 3. 过滤非空结果并添加到集合 bestsellers.addAll(results.filterNotNull()) }
修复后效果
修改后,所有scrapeBookData协程会同时启动:
- 多个链接会先后打印"접근 완료"(取决于页面加载速度)
- 所有协程执行到
delay(3000)时会挂起,协程调度器会切换到其他未挂起的协程继续执行 - 3秒后,所有挂起的协程会恢复执行,陆续打印"파싱 완료"
额外注意事项
如果你的Browser实例不是线程安全的,可能需要给async指定合适的调度器(比如async(Dispatchers.IO)),避免并发操作带来的线程安全问题。
内容的提问来源于stack exchange,提问作者JAEIK JEONG
相关产品推荐
相关产品推荐

