예외 처리


프로그램에서 처리되지 않는 예외가 발생하면 프로그램이 강제로 종료되는 것처럼, 코루틴도 처리되지 않은 예외가 발생하면 종료된다.

fun main(): Unit = runBlocking {
    launch {
        launch {
            delay(1000)
            throw Error("Some error")
        }

        launch {
            delay(2000)
            println("Will not be printed")
        }

        launch {
            delay(500)
            println("Will be printed")
        }
    }

    launch {
        delay(2000)
        println("Will not be printed")
    }
}

/*
Will be printed
Exception in thread "main" java.lang.Error: Some error
*/

→ launch {}에서 발생한 Error가 전체 프로그램을 종료시켰다.

<aside> ☝🏻 예외는 부모 ↔ 자식 쌍방으로 전파되기 때문에, 중간에 예외를 끊지 않으면 모든 코루틴이 종료된다.

</aside>

코루틴 종료 멈추기


<aside> ☝🏻 코루틴의 에러는 Job을 통해 전파되기 때문에 try-catch나 runCatching으로 감싸도 소용이 없다.

</aside>

fun main(): Unit = runBlocking {
    runCatching {
        launch {
            delay(1000)
            throw Error("Some error")
        }
    }.onFailure {
        println("Will not be printed")
    }
    launch {
        delay(2000)
        println("Will not be printed")
    }
}

/*
Exception in thread "main" java.lang.Error: Some error
*/

SupervisorJob

fun main(): Unit = runBlocking { 
    val scope = CoroutineScope(SupervisorJob())
    scope.launch { 
        delay(1000)
        throw Error("Some error")
    }
    
    scope.launch { 
        delay(2000)
        println("Will be printed")
    }
    
    delay(3000)
}

/*
Exception in thread "DefaultDispatcher-worker-2" java.lang.RuntimeException: Exception while trying to handle coroutine exception
Will be printed
*/

→ launch{}에 SupervisorJob() 객체를 바로 전달해서 사용하는 경우가 있다.