CoroutineScope与runBlocking行为差异:两种launch输出不同的原因
差异原因解析
1. 直接使用launch的场景
直接在runBlocking代码块内调用launch,该协程属于runBlocking自身创建的作用域。
runBlocking的核心特性是:会阻塞当前线程(此处为主线程),直到其作用域内的所有子协程全部执行完成才会返回。你的代码中,awaitAll().sum()执行完毕后,runBlocking并不会立刻返回结果,而是会等待自己作用域内那个delay(5000)的协程执行完毕,因此该协程能走完整个流程,打印出"I am late"和finally块中的"I am finalled"。
2. 使用scope.launch的场景
这里的scope是外部传入的CoroutineScope(Dispatchers.IO),通过它启动的协程属于这个外部作用域,和runBlocking的作用域完全独立。
- 首先,
CoroutineScope本身不会自动取消:你创建的CoroutineScope(Dispatchers.IO)没有绑定任何生命周期,也没有手动调用cancel(),所以当testFun1执行完毕后,这个作用域不会主动取消内部协程。 - 其次,进程终止导致协程中断:如果这段代码在主线程中执行,当
compParallel返回结果、testFun1打印完output后,主线程执行完毕,JVM进程直接终止。此时那个delay(5000)的协程还在等待,还没到打印时机就被强制终止,自然不会输出任何内容。
你之前的误解在于认为CoroutineScope对象被销毁时会自动取消协程,但实际上CoroutineScope只是协程上下文的持有者,它的销毁不会触发协程取消,必须手动调用scope.cancel()才能让内部协程进入取消流程,触发finally块。
内容的提问来源于stack exchange,提问作者windchime
相关产品推荐
相关产品推荐

