首發(fā)于公眾號: DSGtalk1989
32.協(xié)程異常處理
-
異常的傳播
launch
和actor
構(gòu)建器是不傳播異常的,async
和produce
是傳播異常的会钝。這里的傳播說的更容易理解一點(diǎn)叫做蔽豺,往外拋垢箕,即不傳播異常就是在本協(xié)程中自己消化控嗜,異常發(fā)生在本協(xié)程所在的線程庸推;傳播異常表示不在本協(xié)程所在線程發(fā)生蘑辑,異常直接往外拋到啟動該協(xié)程所在的線程洋机。我們看如下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)
我們看到兩個異常分別在協(xié)程的線程和主線程中拋出來一個由于在協(xié)程內(nèi),所以不會造成主線程異常洋魂,一個在主線程绷旗,所以直接跪了。
-
CoroutineExceptionHandler
所以針對上面這種情況副砍,我們應(yīng)該怎么辦衔肢,比如我們想要去catch
一下,針對上面的launch
和await
方法豁翎,我們包裹了try catch
如下
try{
job.join()
}catch (e : Exception){
println(e.toString())
}
try{
deferred.await()
}catch (e : Exception){
println(e.toString())
}
發(fā)現(xiàn)await
是可以捕捉的角骤,join
無法用try catch
捕捉。所以針對這種不傳播異常的心剥,我們應(yīng)該怎么去捕捉它呢邦尊。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學(xué)習(xí)筆記之 1 基礎(chǔ)語法
Kotlin學(xué)習(xí)筆記之 2 基本數(shù)據(jù)類型
Kotlin學(xué)習(xí)筆記之 4 循環(huán)控制
Kotlin學(xué)習(xí)筆記之 8 擴(kuò)展
Kotlin學(xué)習(xí)筆記之 9 數(shù)據(jù)類與密封類
Kotlin學(xué)習(xí)筆記之 12 對象表達(dá)式和對象聲明
Kotlin學(xué)習(xí)筆記之 13 基礎(chǔ)操作符run牢撼、with、let疑苫、also熏版、apply
Kotlin學(xué)習(xí)筆記之 14 包與導(dǎo)入
Kotlin學(xué)習(xí)筆記之 18 函數(shù)
Kotlin學(xué)習(xí)筆記之 19 高階函數(shù)與 lambda 表達(dá)式
Kotlin學(xué)習(xí)筆記之 20 內(nèi)聯(lián)函數(shù)
Kotlin學(xué)習(xí)筆記之 21 解構(gòu)聲明
Kotlin學(xué)習(xí)筆記之 28 協(xié)程基礎(chǔ)
Kotlin學(xué)習(xí)筆記之 29 上下文與調(diào)度器
Kotlin學(xué)習(xí)筆記之 30 協(xié)程取消與超時
Kotlin學(xué)習(xí)筆記之 31 協(xié)程掛起函數(shù)的組合