코루틴에서 실행되는 모든 중단 함수(suspending function)들은 취소 요청에 응답 가능하도록 구현되어야 합니다. 다시말해 중단 함수는 실행 중 취소 가능한 구간마다 취소 요청이 있었는지 확인하고 요청이 있었다면 실행을 즉시 취소하도록 구현되어야 합니다. kotlinx.coroutines 라이브러리의 모든 중단함수는 이러한 취소 요청에 대응 하도록 구현되어 있습니다.
앞서 이야기 한 것처럼 취소를 지원하는 중단 함수들은 실행하는 동안 취소가 가능한 지점마다 현재 코루틴이 취소 되었는지 확인하며, 만약 취소 되었다면 CancellationException 을 발생시키며 종료합니다.
출처: Medium Article
위 글처럼 코루틴의 중요한 특징 중 하나는 취소가 가능하다는 점이다.
이번 글에서는 코루틴의 취소에 대해 알아본다.
코루틴 컨텍스트가 갖고 있는 element 중 Job
인터페이스는 코루틴을 취소하는 cancel
메서드를 제공한다.
cancel
메소드를 호출하면 호출당한 코루틴은 첫 중단점에서 Job
을 끝낸다.
이때 Job
에 자식이 존재하면, 자식들도 취소된다(부모는 영향 x). 또한 취소된 Job
은 새로운 코루틴의 부모로 사용될 수 없다.
suspend fun main(): Unit = coroutineScope {
val job = launch {
repeat(1_000) { i ->
delay(200)
println("job: I'm sleeping $i ...")
}
}
delay(1100L)
// job.cancel()
// job.join() // cancel 이 호출된 뒤 다음 작업을 진행하기 전에 취소 과정이 완료되는 걸 기다리기 위해 join 사용
job.cancelAndJoin() // cancel + join 을 한번에 호출
println("main: I'm tired of waiting!")
println("main: Now I can quit.")
}
// 출력
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
job: I'm sleeping 3 ...
job: I'm sleeping 4 ...
main: I'm tired of waiting!
main: Now I can quit.
Job
이 취소되면 상태는 Cancelling으로 변한다.CancellationException
예외를 던진다.suspend fun main(): Unit = coroutineScope {
val job = Job()
launch(job) { // 새로운 잡이 부모로부터 상속받은 잡을 대체
try {
repeat(1_000) { i ->
delay(Random.nextLong(2000))
println("job: I'm sleeping $i ...")
}
} catch (e: CancellationException) {
println(e)
throw e // 취소된 코루틴이 단지 멈추는 것이 아니라 내부적으로 예외를 사용해 취소됨
} finally {
println("Will Always execute")
}
}
delay(1100L)
job.cancelAndJoin()
println("main: Now I can quit.")
delay(1000)
// 출력
job: I'm sleeping 0 ...
kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelling}@4618452e
Will Always execute
main: Now I can quit.
// or
kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelling}@1a55dda5
Will Always execute
main: Now I can quit.
}
코루틴을 취소하면 CancellationException
이 던져지므로, finally 블록에서 추가 연산 수행이 가능하다고 했다. 하지만 Job
이 이미 Cancelling 상태이므로 중단을 허용하지 않고, 다른 코루틴을 시작하려 하면 이를 무시한다.