Kotlin协程代码在Playground超时报错,求原因解析
Kotlin协程async代码超时报错原因分析
问题描述
我是Kotlin新手,正在学习协程及async的用法。在Kotlin Playground运行一段代码时出现错误:Evaluation stopped while it's taking too long️,但另一段包含延迟操作的代码却能正常运行,想请教报错原因。
报错代码
import kotlinx.coroutines.* import java.util.concurrent.Executors import kotlin.system.measureTimeMillis val executor = Executors.newFixedThreadPool(10).asCoroutineDispatcher() suspend fun fooAsyncS(): Int = fooAsync("").await() fun fooAsync(id: String): Deferred<Int> = GlobalScope.async(executor) { delay(1000) 1 } fun main() = runBlocking { val timeElapsed = measureTimeMillis { fooAsyncS() } println("$timeElapsed") println("Hello") }
正常运行的代码
suspend fun example(): String { println("computing result") delay(5000) return "data" } fun main() = runBlocking { val timeElapsed = measureTimeMillis { launch { example() } } println("$timeElapsed") println("Hello") }
报错原因解析
两段代码的核心差异在于是否阻塞了runBlocking的主协程,结合环境限制导致问题:
报错代码的问题点
fooAsyncS()内部调用了await(),这个方法会阻塞当前的主协程(runBlocking创建的协程),必须等到async子协程执行完成才会继续向下执行。- 你给
async指定了自定义线程池executor,Kotlin Playground的受限环境对自定义线程池的协程调度支持不完善,delay(1000)挂起子协程后,线程池无法正确唤醒它,导致await()一直处于阻塞状态,触发了平台的超时限制。 - 另外,
GlobalScope.async是不推荐的用法,它的生命周期不受控,进一步增加了在受限环境中出问题的概率。
正常代码能运行的原因
measureTimeMillis块里调用的是launch,launch只会启动子协程,不会阻塞主协程。所以measureTimeMillis瞬间执行完成,主协程直接走到println语句,整个程序的主流程很快结束,不会触发超时。至于launch里的delay(5000),因为主流程已经结束,平台不会再等待这个子协程完成。
内容的提问来源于stack exchange,提问作者Petesta
相关产品推荐
相关产品推荐

