launch
和 async
launch
:在协程内部马上抛出异常,未捕获的异常不会被保存, join
中也不会保存和传递异常,可是会接受由父协程传递过来的 JobCancellationException
。async
:不在协程内部马上抛出异常,而将未捕获的异常保存在生成的 Deferred
中,最后抛出时已经回到父协程了。coroutineScope
和 supervisorScope
coroutineScope
内部的异常会向上传播,子协程未捕获的异常会向上传递给父协程,任何一个子协程异常退出,会致使总体的退出。supervisorScope
内部的异常不会向上传播,一个子协程异常退出,不会影响父协程和兄弟协程的运行。try {
coroutineScope {
try {
val child1 = launch {
log("Child1 is started")
delay(100)
throw ArithmeticException("Child1 error")
}
child1.join()
} catch (e: Exception) {
log("Child1: $e")
}
try {
val child2 = launch {
log("Child2 is started")
delay(1000)
log("Child2 is finished")
}
child2.join()
} catch (e: Exception) {
log("Child2: $e")
}
}
} catch (e: Exception) {
log("Parent: $e")
}
复制代码
切换外层的 coroutineScope
和 supervisorScope
,再对 child1
切换使用 launch
和 async
,最后获得下表html
条件 | child1 的 catch | child 2 的 catch | parent 的 catch |
---|---|---|---|
coroutineScope + launch | JobCancellationException | Child1 error | |
coroutineScope + launch + join | JobCancellationException | JobCancellationException | Child1 error |
coroutineScope + async | JobCancellationException | Child1 error | |
coroutineScope + async + await | Child1 error | JobCancellationException | Child1 error |
supervisorScope + launch | JobCancellationException | Child1 error | |
supervisorScope + launch + join | Child1 error | JobCancellationException | Child1 error |
supervisorScope + async | |||
supervisorScope + async + await | Child1 error |
launch
不管其父协程做用域是 coroutineScope
仍是 supervisorScope
,都会致使整个父协程做用域范围内的协程的退出。而且由于 join
不会保存和传播异常,即便 launch
自己在外部 try/catch
里执行了 join
,catch
中捕获的也只是由父协程发出的取消。async
async
由于是将未捕获的异常保存在生成的 Deferred
中,在父协程做用域是 coroutineScope
时,虽然一样由于将异常抛给父协程致使整个父协程做用域范围内的协程的退出。可是在外部 try/catch
里执行 await
时, catch
也可以捕获发生在 async
内部的异常。在父协程做用域是 supervisorScope
是,该 async
的崩溃不会影响兄弟协程和父协程其余代码的运行。spa
一般状况下,使用经常使用的 coroutineScope
+ launch
,将异常捕获写在 launch
中就能够了。.net
但在同时运行多个子协程时,有两种状况下,使用 supervisorScope
+ async
更为便利。code
try/catch
,且一个协程的崩溃不能致使全部协程的退出try/catch
,可是对全部协程抛出的异常处理逻辑是相同的,且一个协程的崩溃应致使全部协程的退出参考文章 :协程
Kotlin协程中的launch/join和async/await之间有什么区别htm
异常处理作用域