TIL

5강 코루틴의 예외 처리와 Job의 상태 변화

루트 코루틴

fun main(): Unit = runBlocking {
  val job1 = launch {
    delay(1_000L)
    printWithThread("Job 1")
  }
  val job2 = launch {
    delay(1_000L)
    printWithThread("Job 2")
} }

CoroutineScope

fun main(): Unit = runBlocking {
  val job1 = CoroutineScope(Dispatchers.Default).launch {
    delay(1_000L)
    printWithThread("Job 1")
  }
  val job2 = CoroutineScope(Dispatchers.Default).launch {
    delay(1_000L)
    printWithThread("Job 2")
  } 
}

launch와 async의 예외 발생 차이

fun main(): Unit = runBlocking {
  val job1 = CoroutineScope(Dispatchers.Default).launch {
    throw IllegalArgumentException()
  }
  delay(1_000L) 
}

// 출력 결과
// Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IllegalArgumentException
fun main(): Unit = runBlocking {
  val job = CoroutineScope(Dispatchers.Default).async {
    throw IllegalArgumentException()
  }
  delay(1_000L)
  // job.await() 호출했다면 이 시점에 예외 출력
}

// 출력 결과
//

코루틴의 예외 전파

fun main(): Unit = runBlocking {
  val job = async {
    throw IllegalArgumentException()
  }
  delay(1_000L)
}

// 출력 결과
// Exception in thread "main" java.lang.IllegalArgumentException

SupervisorJob

fun main(): Unit = runBlocking {
  val job = async(SupervisorJob()) {
    throw IllegalArgumentException()
}
  delay(1_000L)
}

// 출력 결과 (예외를 출력하지 않음)
//

코루틴 예외를 다루는 방법

[1] 직관적인 try-catch-finally

fun main(): Unit = runBlocking {
val job = launch() { // async도 동일
    try {
      throw IllegalArgumentException()
    } catch (e: IllegalArgumentException) {
      printWithThread("정상 종료")
    } 
  }
}

// 출력 결과
// [main @coroutine#2] 정상 종료

[2] CoroutineExceptionHandler

fun main(): Unit = runBlocking {
  val exceptionHandler = CoroutineExceptionHandler { _, _ ->
    printWithThread("예외 발생")
  }
  val job = CoroutineScope(Dispatchers.Default).launch(exceptionHandler) {
    throw IllegalArgumentException()
  }
  delay(1_000L)
}

// 출력 결과
// [DefaultDispatcher-worker-1 @coroutine#2] 예외 발생

코루틴 취소와 코루틴 예외의 차이

Job(코루틴의 Life Cycle