https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancelling-coroutine-execution
cancel
cancel을 통해 job을 취소할 수 있다. 공식 문서에서 여러 예제에서 cancel을 할 때 어떤 상황인지에 따라서 예상한 결과가 나오는 경우도 있고 안 나온 경우도 있다.
launch에 Dispatchers.Default 을 통해 메인 스레드가 아닌 스레드를 사용할 수 있다.
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) { // computation loop, just wastes CPU
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancel() // cancels the job and waits for its completion
job.join()
println("main: Now I can quit.")
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
job: I'm sleeping 3 ...
job: I'm sleeping 4 ...
main: Now I can quit.
다른 스레드를 사용하므로 cancel 이후에도 출력을 하는 것을 볼 수 있는데 1300초일 때 delay(1300L)이 끝났으므로 I'm tired of wating을 출력한다. 이 때 cancel이후 join을 하기 때문에 코루틴이 종료될 때까지 기다린다. 3,4 까지 출력 후 Now I can quit을 출력한다. cancel과 join을 한번에 쓸 때 cancelAndJoin 을 쓸 수 있다.
만약 Dispatchers.Default을 사용하지 않으면
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.
위와 같이 출력한다. 스레드를 하나만 사용하고 있기 때문에 1300초 이후 cancel을 하더라도 이미 코루틴에서 스레드를 사용하고 있기 때문에 사용하지 못한다.
al startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) { // computation loop, just wastes CPU
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancel() // cancels the job and waits for its completion
println("main: Now I can quit.")
-------------------
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
main: Now I can quit.
job: I'm sleeping 3 ...
job: I'm sleeping 4 ...
job.cancel()이후 join을 없애면 위와 같이 출력한다 (Dispatchers.Default 사용시) join이 없기 때문에 단순히 두 스레드를 이용해서 처리하는 것과 같다.
위와 같이 다른 스레드를 쓸 때 cancel과 join을 함께 써줘야 원하는 취소가 가능하고, 하나의 스레드만을 사용할 때는 cancel을 사용해서 취소할 수 있다. 하지만 단순연산이 아닌 delay와 같은 함수를 쓸 때는 cancel이 되는데
Coroutine cancellation is cooperative. A coroutine code has to cooperate to be cancellable. All the suspending functions in kotlinx.coroutines are cancellable.
을 통해 확인 할 수 있다.
isActive을 통해 취소된 상태인지 아닌지 확인할 수 있다. while의 조건으로 isActive을 넣어서 처리할 수 있다.
delay와 같은 취소 가능한 suspending 함수들은 취소 상태가 되면 CancellationException 을 던진다. 이 때 try와 finally문을 통해 제어하면 된다.
withContext(NonCancellable)을 통해 취소가 불가능하게 할 수도 있다.
withTimeout를 통해 시간이 지난후에 종료하도록 할 수 있다.
withTimeoutOrNull을 통해 시간이 지나 종료될 때 null을 리턴하게 할 수 있다.
'Kotlin > 공부노트' 카테고리의 다른 글
Coroutine - 5. suspending function, async (0) | 2022.04.04 |
---|---|
Coroutine - 3. job, join (0) | 2022.03.17 |
Coroutine - 2. Structured concurrency, suspend, coroutineScope (0) | 2022.03.12 |
Coroutine - 1. launch, runBlocking, delay (0) | 2022.03.10 |
댓글