kotlin:coroutineScope 和 supervisorScope的不同点
一,两者的相同点和不同点:
共同点
首先,我们来看一下 coroutineScope
和 supervisorScope
的共同特性:
- 作用域嵌套:两者均可以嵌套在其他作用域中。
- 结构化并发:它们都强制执行结构化并发,即作用域会等待所有启动的子协程完成之后才会完成自身。
- 取消传播:从父协程向子协程传播取消信号。如果父协程被取消,所有子协程也会被取消。
不同点
coroutineScope
和 supervisorScope
主要区别在于它们对异常处理和异常传播的方式:
-
异常传播:
coroutineScope
:任何子协程抛出的异常都会立即取消整个作用域及其内的其他子协程。supervisorScope
:子协程抛出的异常不会导致整个作用域或其他子协程的立即取消。失败的协程将独立处理,允许其他协程继续执行。
-
使用场景:
coroutineScope
非常适合于一组相关任务,如果其中一个任务失败,其他任务也应该一同取消。supervisorScope
在你希望独立处理子协程的失败并保持其他任务运行时非常有用,例如启动多个独立的操作。
二,例子:coroutineScope子协程内的异常会影响整个到作用域内其他子协程
代码:
//处理按钮点击事件
binding.button1.setOnClickListener {
runBlocking {
try {
coroutineScope {
launch {
println("子协程 1 开始")
throw Exception("子协程失败")
}
launch {
println("子协程 2 开始")
delay(100)
println("因为其他子协程失败,这段代码不会被打印。")
}
}
} catch (e: Exception) {
println("捕获异常: ${e.message}")
}
}
}
运行结果:

三,例子:supervisorScope子协程的异常不会传播到父协程
注意起作用的只有一级子协程
代码:
//处理按钮点击事件
binding.button2.setOnClickListener {
runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("捕捉到了异常: $e")
}
supervisorScope {
launch(handler) {
println("子协程 1 开始")
delay(100)
throw Exception("子协程1失败")
}
launch {
println("子协程 2 开始")
delay(200)
println("子协程 2 成功完成!")
}
}
}
}
运行结果:
