runBlocking
코루틴, job1
코루틴, job2
코루틴runBlocking
으로 만들어진 코루틴이다.fun main(): Unit = runBlocking {
val job1 = launch {
delay(1_000L)
printWithThread("Job 1")
}
val job2 = launch {
delay(1_000L)
printWithThread("Job 2")
} }
CorutineScope
를 사용하면 된다.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")
}
}
Dispatchers.Default
로 새로운 스레드에서 코루틴을 실행 시키며 각각의 launch
가 루트 코루틴이 되었다.launch
함수는 예외가 발생하자마자 해당 예외를 출력하고 코루틴이 종료된다.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
async
함수는 예외가 발생해도 예외를 출력하지 않는다.
await
함수를 써야 한다.async
는 값을 반환할 수 있기에 값을 반환할 때 예외를 처리하도록 한 것이다.fun main(): Unit = runBlocking {
val job = CoroutineScope(Dispatchers.Default).async {
throw IllegalArgumentException()
}
delay(1_000L)
// job.await() 호출했다면 이 시점에 예외 출력
}
// 출력 결과
//
CorutineScope
로 생성한 루트 코루틴이 아닌 자식 코루틴이 되면 async
를 사용해도 예외가 바로 출력된다.
runBlocking
에 예외가 전파되어 코루틴을 종료하게 되고 runBlocking
의 경우 예외를 만나면 바로 출력하게 된다.fun main(): Unit = runBlocking {
val job = async {
throw IllegalArgumentException()
}
delay(1_000L)
}
// 출력 결과
// Exception in thread "main" java.lang.IllegalArgumentException
SupervisorJob()
을 사용하면 된다.
async
의 원래 행동 패턴대로 동작한다.fun main(): Unit = runBlocking {
val job = async(SupervisorJob()) {
throw IllegalArgumentException()
}
delay(1_000L)
}
// 출력 결과 (예외를 출력하지 않음)
//
fun main(): Unit = runBlocking {
val job = launch() { // async도 동일
try {
throw IllegalArgumentException()
} catch (e: IllegalArgumentException) {
printWithThread("정상 종료")
}
}
}
// 출력 결과
// [main @coroutine#2] 정상 종료
try-catch
로 예외를 잡으면 코루틴이 종료되지 않게 할 수 있고 적절한 처리도 할 수 있다.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] 예외 발생
CoroutineExceptionHandler
주의할 점
launch
에만 적용 가능하다.CancellationException
이 발생하는 것이었다.CancellationException
이 발생한 경우 취소로 간주하고 부모 코루틴에게 전파하지 않는다.CancellationException
인지 아닌지에 상관없이 CANCELLING
상태가 된다.ACTIVE
상태에서 성공하면 COMPLETING
상태로 넘어간다.