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에 의해 취소되지 않음