launch에 의해 반환되는 job 객체의 cacel을 호출하면 코루틴을 취소할 수 있다.kotlinx.coroutines 패키지의 suspend 함수인 yeild() 또는 delay() 함수를 호출하면 취소에 협조할 수 있다.job1)은 취소에 협조 했기에 잘 취소되어 job2만 실행되었다.fun main(): Unit = runBlocking {
val job1 = launch {
delay(1_000L)
printWithThread("Job 1")
}
val job2 = launch {
delay(1_000L)
printWithThread("Job 2")
}
delay(100L) // 첫번째 코루틴 실행을 잠시 기다린다.
job1.cancel()
}
// 실행 결과
// [main @coroutine#3] Job 2
main 스레드 제어 흐름은 다음과 같다.
job1 코루틴을 실행하려 하지만 1초 기다려야 해서 job2를 봄job2 코루틴을 실행하려 하지만 1초 기다려야 해서 넘어감delay 중) 잠시 대기job1.cancel을 호출job1을 실행하려 하지만 취소되었기에 실행하지 않는다.job2 실행fun main(): Unit = runBlocking {
val job = launch {
delay(10L)
printWithThread("Job 1")
}
delay(100L)
job.cancel()
}
// 실행 결과
// [main @coroutine#2] Job 1
main 스레드 제어 흐름
job 코루틴을 실행하려 하지만 0.01초 대기cancel 호출 전에 job 코루틴 실행yeild나 delay 같은 제어를 넘기는 suspend 함수 호출이 필수적이다.
cancel 코드가 존재해도 cancel 코드에 도달하지 못한채 코루틴이 전부 실행되고 만다.isActive
isActive 프로퍼티에 접근할 수 있다.Dispatchers.Default
Dispatchers.Default을 launch와 함께 사용하면 코루틴을 다른 스레드에서 실행시킬 수 있다.fun main(): Unit = runBlocking {
val job = launch(Dispatchers.Default) {
var i = 1
var nextPrintTime = System.currentTimeMillis() // 현재 시각
while (i <= 5) { // 5번 반복
if (nextPrintTime <= System.currentTimeMillis()) {
printWithThread("${i++}번째 출력")
nextPrintTime += 1_000L // 1초 후에 다시 출력되도록
if (!isActive) { //
throw CancellationException()
}
}
}
delay(100L)
printWithThread("취소 시작")
job.cancel()
}
// 실행 결과
// [DefaultDispatcher-worker-1 @coroutine#2] 1 !
// [main @coroutine#1] 취소 시작
main 스레드가 cancel를 호출해버린 것Dispatchers.Default가 없었다면 main 스레드가 while을 돌면서 제어를 점유하고 있기 때문에 취소가 동작하지 않았을 것이다.
delay() 같은 함수도 취소를 감지하면 CancellationException을 던지며 코루틴을 종료하게 된다.
catch로 무시하면 코루틴은 취소되지 않는다.fun main(): Unit = runBlocking {
val job = launch {
try {
delay(1_000L)
} catch (e: CancellationException) { // 예외 무시
}
printWithThread("delay에 의해 취소되지 않음")
}
delay(100L)
printWithThread("취소 시작")
job.cancel()
}
// 실행 결과
// [main @coroutine#1] 취소 시작
// [main @coroutine#2] delay에 의해 취소되지 않음