환경
kotlin coroutine version : 1.6.1
Coroutine Builder 란?
Coroutine을 실행할 때 사용하는 여러 가지 함수를 뜻한다. 예를 들어 launch(), async(), runBlocking() 등이 있다.
launch()
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
launch는 동시성 작업이 결과를 만들어내지 않는 경우에 적합하다. 위의 launch() 원형을 살펴보면, Job으로서 coroutine 참조를 반환하고 있다. 그리고 인자의 block을 보면, Unit 타입을 반환하는 람타를 인자로 받고 있다.
async()
launch() 와는 다르게 동시성 작업의 결과가 필요한 경우에 async() 빌더를 사용한다.
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyDeferredCoroutine(newContext, block) else
DeferredCoroutine<T>(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
async() 빌더 원형을 살펴보면, DeferredCoroutine 인스턴스를 반환하고, 이 인스턴스는 job의 하위 타입으로 await() 메서드를 통해 계산 결과에 접근할 수 있다. 이때 await()는 async() 빌더로 실행된 작업이 완료되거나, 취소될 때 까지 현재 코루틴을 일시 중단 시킨다.
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
suspend fun main() {
val message = GlobalScope.async {
delay(100)
"abc"
}
val count = GlobalScope.async {
delay(100)
3
}
delay(200)
val result = message.await().repeat(count.await())
println(result)
}
위 코드의 실행 결과는 abcabcabc 이다. count.await()의 값은 3이고, message.await().repeat(3)에 의해, abc가 3번 반복되어 리턴된다. main()을 suspend로 하여, 두 개의 Deferred 작업에 대해 직접 await() 메서드를 호출했다.
Deferred란 '연기' 라는 의미로 미래의 어느 시점에 결과값이 수신된다 라고 생각하면 편할 것 같다. 코틀린에서 Deferred는 결과값이 없는 비동기 작업을 확장하여 결과값이 있는 비동기작업으로 제공하기 위한 인터페이스 이다.
runBlocking()
위의, launch(), async() 빌더는 일시중단함수 내부에서 스레드 호출을 블럭시키지는 않고 백그라운드 스레드를 공유하는 풀을 통해 작업을 실행한다. 반대로 runBlocking() 빌더는 디폴트로 현재 스레드에서 실행되는 작업을 생성하고 해당 작업이 완료될 때 까지 현재 스레드의 실행을 블럭시킨다. 즉 runBlocking() 빌더를 메인스레드에서 실행하면, 메인스레드는 블럭되고, runBlocking() 작업을 수행한다. 그렇기에 runBlocking()을 다른 코루틴 작업에서 수행해서는 안된다.
Reference
- 코틀린 완벽 가이드 | 알렉세이 세두노프 지음, 오현석 옮김
- http://kotlinlang.org/docs/coroutines-overview.html
'Android > Kotlin' 카테고리의 다른 글
[Kotlin] Flow<List<T>> 에서 List<T>로 변환하기. (0) | 2022.09.15 |
---|---|
[Kotlin/Plugin] Json으로 data class 추출하기 (0) | 2022.07.28 |
[Kotlin] Object (0) | 2022.06.22 |
[Kotlin] @Volatile 키워드란? (0) | 2022.06.15 |
[Kotlin] Scope Function (작성중) (0) | 2022.05.22 |