/* 본 게시물은 ' Do it 코틀린 프로그래밍 | with 황영덕 ' 의 내용을 토대로 작성되었습니다. */
참고 자료
[URL] :
#코루틴
1. 코틀린 코루틴의 디스패처(코루틴의 문맥)
코루틴은 항상 특정 문맥에서 실행된다. 이때 어떤 문맥에서 코루틴을 실행할지는 디스패처가 결정한다.
- Dispatchers.Default : 기본 문맥인 CommonPool에서 실행되고 GlobalScope.launch{...} 와 launch(Dispatchers.Default){...} 는 같은 표현이다. 스레드를 새로 생성하지 않고 기존에 있는 것을 이용한다. 이는 연산 중심의 코드에 적합하다.
- Dispatchers.IO : 입출력 위주의 동작을 하는 코드에 적합한 공유된 풀이다. 따라서 블로킹 동작이 많은 파일이나 소켓 I/O 처리에 사용하면 좋다.
- Dispatchers.Unconfined : 호출한 컨텍스트를 기본으로 사용하는데 중단 후 다시 실행될 때 컨텍스트가 바뀌면 바뀐 컨텍스트를 따라 가는 특이한 디스패처이다. 이 옵션의 사용은 권장하지 않는다.
- Dispatchers.Main : 안드로이드 기본 스레드에서 코루틴 실행. UI와 상호작용에 최적화됨.
2. 기본 동작 제어하기
코루틴으로 시간을 세는 반복함수를 만들어보자.
fun main() { runBlocking {
GlobalScope.launch { // 만일 launch만 사용하면 종료되지 않음
repeat(1000){
println("time: $it")
delay(1000L)
}
}
delay(3000L)
}
}
실행 결과
GlobalScope로 생명주기를 한정했기 때문에 첫 번째 결과는 2까지만 출력하고 종료되었지만 GlobalScope를 지우면 모든 횟수를 진행할 때까지 프로그램이 종료되지 않는다.
코루틴 작업 취소하기
cancel() 함수를 사용해보자.
fun main() { runBlocking {
val job = launch { // 만일 launch만 사용하면 종료되지 않음
repeat(1000){
println("time: $it")
delay(1000L)
}
}
delay(3000L)
job.cancel()
}
}
cancel() 함수에 의해 3초 뒤 repeat() 함수의 반복 실행이 취소된다.
finally 실행 보장
try~finally 구문을 사용해 finally 블록에서 코루틴의 종료 과정을 처리하도록 할 수 있다. 단 finally 블록에 식나이 걸리는 작업이나 지연 함수가 사용될 경우 실행을 보장하기 위해서는 NonCancellable 문맥에서 작동해야한다. 이것을 위해 withContext(NonCancellable){...} 을 사용해야한다.
fun main() { runBlocking {
val job = launch {
try {
repeat(1000) {
println("time: $it")
delay(1000L)
}
} finally { // finally의 완전한 실행 보장
withContext(NonCancellable){
println("finally start")
delay(1000L) //NonCancellable 문맥에서 지연 함수 사용가능
println("Non-cancel")
}
}
}
delay(3000L)
job.cancelAndJoin()
println("Exit")
}
}
실행 결과
실행 상태의 판단
만일 코드를 중단하기 위해 코루틴에 조건식을 넣으려고 할 때 연산이 마무리되기 전까지는 조건식에 의해 루틴이 중단되지 않는다는 것을 기억해야 한다.
fun main() { runBlocking {
val startTime = System.currentTimeMillis()
val job = GlobalScope.launch {
var nextPrintTime = startTime
var i = 0
while(i < 5){ //코루틴에 조건식을 넣으면 연산이 마무리 되기 전까지 조건식에 의해 루틴이 중단되지 않는다.
if(System.currentTimeMillis() >= nextPrintTime){
println("${i++}")
nextPrintTime += 1000L
}
}
}
delay(2000L)
println("main: 2second gone")
job.cancelAndJoin()
println("main: Quit")
}
}
실행 결과
결과로 보아 조건문의 연산이 완료되기 전까지 코루틴에서 탈출을 못하는 것을 확인할 수 있다. 이를 해결하기 위해서는 while(i<5) 대신 while(isActive)을 사용하면 해결이 가능하다.