Kotlin學習筆記之 32 協程異常處理

首發于公眾號: DSGtalk1989

32.協程異常處理

  • 異常的傳播

launchactor構建器是不傳播異常的,asyncproduce是傳播異常的。這里的傳播說的更容易理解一點叫做,往外拋,即不傳播異常就是在本協程中自己消化,異常發生在本協程所在的線程;傳播異常表示不在本協程所在線程發生,異常直接往外拋到啟動該協程所在的線程。我們看如下demo

val job = GlobalScope.launch {
    println("${Thread.currentThread().name}   :   Throwing exception from launch")
    throw IndexOutOfBoundsException()
}
job.join()
println("Joined failed job")
val deferred = GlobalScope.async {
    println("${Thread.currentThread().name}   :   Throwing exception from async")
    throw ArithmeticException()
}
deferred.await()
println("Unreached")

控制臺打印

DefaultDispatcher-worker-1   :   Throwing exception from launch
Exception in thread "DefaultDispatcher-worker-1" java.lang.IndexOutOfBoundsException
    at salamanca.DestructTestKt$main$1$job$1.invokeSuspend(DestructTest.kt:52)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
Joined failed job
DefaultDispatcher-worker-1   :   Throwing exception from async
Exception in thread "main" java.lang.ArithmeticException
    at salamanca.DestructTestKt$main$1$deferred$1.invokeSuspend(DestructTest.kt:58)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)

我們看到兩個異常分別在協程的線程和主線程中拋出來一個由于在協程內,所以不會造成主線程異常,一個在主線程,所以直接跪了。

  • CoroutineExceptionHandler

所以針對上面這種情況,我們應該怎么辦,比如我們想要去catch一下,針對上面的launchawait方法,我們包裹了try catch如下

try{
    job.join()
}catch (e : Exception){
    println(e.toString())
}

try{
    deferred.await()
}catch (e : Exception){
    println(e.toString())
}

發現await是可以捕捉的,join無法用try catch捕捉。所以針對這種不傳播異常的,我們應該怎么去捕捉它呢。CoroutineExceptionHandler登場。

我們將上面的代碼作如下改動

val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}
val job = GlobalScope.launch(handler) {
    println("${Thread.currentThread().name}   :   Throwing exception from launch")
    throw IndexOutOfBoundsException()
}
job.join()

打印如下,舒坦。

DefaultDispatcher-worker-1   :   Throwing exception from launch
Caught java.lang.IndexOutOfBoundsException

Kotlin學習筆記之 1 基礎語法

Kotlin學習筆記之 2 基本數據類型

Kotlin學習筆記之 3 條件控制

Kotlin學習筆記之 4 循環控制

Kotlin學習筆記之 5 類和對象

Kotlin學習筆記之 6 繼承

Kotlin學習筆記之 7 接口

Kotlin學習筆記之 8 擴展

Kotlin學習筆記之 9 數據類與密封類

Kotlin學習筆記之 10 泛型

Kotlin學習筆記之 11 枚舉類

Kotlin學習筆記之 12 對象表達式和對象聲明

Kotlin學習筆記之 13 基礎操作符run、with、let、also、apply

Kotlin學習筆記之 14 包與導入

Kotlin學習筆記之 15 伴生對象

Kotlin學習筆記之 16 委托

Kotlin學習筆記之 17 可觀察屬性

Kotlin學習筆記之 18 函數

Kotlin學習筆記之 19 高階函數與 lambda 表達式

Kotlin學習筆記之 20 內聯函數

Kotlin學習筆記之 21 解構聲明

Kotlin學習筆記之 22 集合

Kotlin學習筆記之 23 相等判斷

Kotlin學習筆記之 24 操作符重載

Kotlin學習筆記之 25 異常捕捉

Kotlin學習筆記之 26 反射

Kotlin學習筆記之 27 類型別名

Kotlin學習筆記之 28 協程基礎

Kotlin學習筆記之 29 上下文與調度器

Kotlin學習筆記之 30 協程取消與超時

Kotlin學習筆記之 31 協程掛起函數的組合

Kotlin學習筆記之 32 協程異常處理

Kotlin學習筆記之 33 協程 & Retrofit

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容