launch
, actor
async
, produce
launch
, actor
는 uncaughtExceptionHandler
와 비슷하게 잡히지 않은 예외로 다룸.async
, produce
는 await
이나 receive
를 통해 사용자가 마지막 예외를 소비하는지에 의존.import kotlinx.coroutines.*
@OptIn(DelicateCoroutinesApi::class)
fun main() = runBlocking {
// 이 부분에서 GlobalScope를 빼면 예외가 전파되어 print를 호출하고 종료됨.
val job = GlobalScope.launch {
println("Throwing exception from launch")
throw IndexOutOfBoundsException()
}
job.join()
println("joined failed job")
val deferred = GlobalScope.async {
println("Throwing exception from async")
throw ArithmeticException()
}
try {
deferred.await()
println("Unreached")
} catch (e: ArithmeticException) {
println("Caught ArithmeticException")
}
}
실행결과
Throwing exception from launch
Exception in thread "DefaultDispatcher-worker-1" java.lang.IndexOutOfBoundsException
at MainKt$main$1$job$1.invokeSuspend(Main.kt:7)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@5428648a, Dispatchers.Default]
joined failed job
Throwing exception from async
Caught ArithmeticException
launch
는 잡히지 않은 예외로 다룸.
runBlocking
코루틴 안에서 GlobalScope.launch
를 사용함.
잡히지 않은 예외를 콘솔에 출력하도록 기본 동작을 커스텀 할 수 있음.
root 코루틴의 CoroutineContext
인 CoroutineExceptionHandler
이 있음.
catch
블록으로 사용됨.CoroutineContext
에 추가된 CoroutineExceptionHandler
는 사용되지 않음.async 코루틴 빌더는 모든 예외를 잡아 Deferred 객체에 나타내므로
CoroutineExceptionHandler가 아무런 효과가 없음.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
}
fun main() = runBlocking<Unit> {
val job = GlobalScope.launch(handler) { // root coroutine, running in GlobalScope
throw AssertionError()
}
val deferred = GlobalScope.async(handler) { // also root, but async instead of launch
throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
}
joinAll(job, deferred)
}
실행결괴
CoroutineExceptionHandler got java.lang.AssertionError
https://myungpyo.medium.com/코루틴-공식-가이드-자세히-읽기-part-6-dd7796150ff3
CancellationException
을 사용함.
catch
를 사용하여 추가적인 디버깅 정보를 위해서만 사용해야함.import kotlinx.coroutines.*
fun main() = runBlocking<Unit> {
val job = launch {
val child = launch {
try {
delay(Long.MAX_VALUE)
} finally {
println("Child is cancelled")
}
}
yield()
println("Cancelling child")
child.cancel()
child.join()
yield()
println("Parent is not cancelled")
}
job.join()
}
실행결과
Cancelling child
Child is cancelled
Parent is not cancelled
CoroutineExceptionHandler
의 구현식은 자식 코루틴들을 위해 사용되지 않음