IT/Kotlin
Coroutine Async
물통꿀꿀이
2020. 11. 22. 16:22
코루틴에서 기본인 것 같지만 놓치는 부분이 있을 수도 있기에 정리해보려고 한다.
Async
async는 자주 사용해왔던 launch와 거의 흡사하다. 그러나 차이점이라면 launch는 job을 반환하는데에 비해 async는 Deferred라는 값을 반환한다. (아래 참조)
fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> (source)
그렇다면 Deferred가 무엇이길래 조금 다른 것일까?
엄밀히 말하면 Deferred도 job의 종류 중 하나이긴 한데 Deferred는 말 그대로 결과는 나중에 알려주겠다는 의미이다.
await()라는 메소드를 통해 값을 얻을 수 있기 때문에 실행 중 스레드를 block 하지 않는다.
suspend fun concurrentSum(): Int = coroutineScope {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
one.await() + two.await()
}
때문에 위의 코드에서 확인 할 수 있듯이, one/two는 각각의 코루틴에서 실행되고 await를 통해 값을 얻고 합쳐진다.
Lazy async
Async를 좀 더 재미있게 쓸 수도 있다. 바로 lazy를 통한 것인데 코드로 먼저 확인해 보자.
val time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
// some computation
one.start() // start the first one
two.start() // start the second one
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
async의 CoroutineStart에 Lazy를 넣을 수 있다.
그런데 사실 Lazy를 쓰고 않쓰고는 결과상의 차이는 없다. 단지, await()를 호출 하는 시점에 코루틴을 시작한다는 점이 조금 다를 수 있다. (기존에는 async에서 바로 코루틴이 실행되었기 때문에)