kotlin 例外処理 ---- 例外 CancellationException と他の例外との違い、コルーチンでの例外処理の順番を取り消す

CancellationException は、コルーチンがコルーチンをキャンセルするために特別に使用され、他の例外とは処理が異なります。

  • コルーチンは内部で CancellationException を使用して操作をキャンセルしますが、この例外は無視されます。
  • 子コルーチンがキャンセルされても、親コルーチンはキャンセルされません。(その他の例外であれば親コルーチンも終了!)
  • コルーチンが CancellationException 以外の例外に遭遇した場合、その例外を使用して親コルーチンをキャンセルします。親コルーチンと子コルーチンの両方が終了すると、例外は親コルーチンによって処理されます。

次の例では、文 println("Exception capture ${exception.message}") が最後に実行されます。これは、上記の 3 番目のポイントで、親コルーチンがすべての子コルーチンで例外を処理すると述べているためです。すべて実行されます。

step1: 2 番目の子コルーチンが例外をスローした場合、親コルーチンに CancellationException をスローして、親コルーチンをキャンセルします。

ステップ 2: 親コルーチンが最初のサブコルーチンに例外を渡し、最初のサブコルーチンが例外をキャッチして最後に実行し、リソースをクリーンアップします。(ここでリソースをクリーンアップする場合は withContext(NonCancellable) パッケージを使用する必要があります。これにより、リソースのクリーンアップ作業が他の例外によって妨げられないためです)

Step3: サブコルーチンがすべて実行されると、ここで最初のサブコルーチンが最終的に実行され、ハンドラーを使用して 2 番目のサブコルーチンによってスローされた例外を処理します。

@Test
fun coroutineExceptionHandlerTest2() = runBlocking<Unit> {
    var handler = CoroutineExceptionHandler{ _ , exception ->
        println("异常捕获 ${exception.message}")
    }
    var job1 = GlobalScope.launch(handler) {
        launch {
            try {
                println("第一个子协程进入")
                delay(Long.MAX_VALUE)
            } catch (e : java.lang.Exception) {
                println("第一个子协程捕获到异常,${e.message}")
            } finally {
                withContext(NonCancellable) {
                    println("第一个子协程准备清理资源")
                    delay(5000)
                    println("第一个子协程准备清理资源完毕")
                }
            }
        }
        launch {
            println("第二个子协程进入")
            delay(1000)
            throw ArithmeticException("抛出一个算数异常!!!!!!!!!")
        }
    }
    job1.join()
}
第一个子协程进入
第二个子协程进入
第一个子协程捕获到异常,Parent job is Cancelling
第一个子协程准备清理资源
第一个子协程准备清理资源完毕
异常捕获 抛出一个算数异常!!!!!!!!!

 

おすすめ

転載: blog.csdn.net/mldxs/article/details/127178858