launch() 함수는 코루틴 종료를 기다리거나 취소하는 데 사용할 수 있는 Job 객체를 반환합니다. 그러나 launch()를 사용하여 시작된 코루틴에서 결과를 반환할 방법이 없습니다. 작업을 비동기적으로 실행하고 응답을 받으려면 launch() 대신 async()를 사용하십시오.
async() 함수는 launch()와 동일한 매개변수를 사용하므로 동일한 방식으로 async() 및 launch()를 사용하여 생성된 코루틴의 context 및 start 속성을 구성할 수 있습니다. 그러나 차이점은 async()가 다른 메서드 중에서 코루틴, 취소 등의 상태를 확인하기 위해 await() 메서드가 있는 Deferred<T> future 객체를 반환한다는 것입니다. wait() 호출은 실행 흐름을 차단하지만 실행 스레드는 차단하지 않습니다. 따라서 호출자의 코드와 async()에 의해 시작된 코루틴 내의 코드는 동시에 실행할 수 있습니다. await() 호출은 결국 async()를 사용하여 시작된 코루틴의 결과를 반환합니다. async()를 사용하여 시작된 코루틴에서 예외가 발생하면 해당 예외는 await() 호출을 통해 호출자에게 전파됩니다
우리는 다음 장에서 async()와 await()를 사용할 것이지만, 여기서는 이 함수들을 간단히 맛보도록 하겠습니다. 다음 코드에서는 시스템에서 비동기적으로 사용 가능한 코어 수를 얻습니다. Dispatchers.Default 인수는 선택 사항이며, 생략하면 코루틴은 상속된 scope 의 디스패처에서 실행됩니다. 이 예제에서는 단일 스레드 scope 이므로 코루틴은 호출자와 동일한 스레드에서 실행됩니다. 그러나 다중 스레드 디스패처의 scope에서 실행될 때 코루틴은 해당 디스패처의 스레드중 하나에서 실행됩니다.
import kotlinx.coroutines.*
runBlocking {
val count: Deferred<Int> = async(Dispatchers.Default) {
println("fetching in ${Thread.currentThread()}")
Runtime.getRuntime().availableProcessors()
}
println("Called the function in ${Thread.currentThread()}")
println("Number of cores is ${count.await()}")
}
요청이 전달되면 메인 스레드는 async() 호출 후 print 문을 실행합니다. await()에 대한 호출은 async()에 의해 시작된 코루틴이 완료될 때까지 기다립니다. 마지막 print 문은 코루틴에서 받은 응답을 print 합니다. output 에서 이것을 살펴보겠습니다.
Called the function in Thread[main,5,main]
fetching in Thread[DefaultDispatcher-worker-1,5,main]
Number of cores is 8
output은 내 시스템의 코어 수를 보여줍니다. 당신의 output은 다를 수 있습니다. 코루틴이 DefaultDispatcher 풀의 스레드에서 실행되었음을 알 수 있습니다. async() 호출에서 Dispatchers.Default 인수를 제거하고 코드를 다시 실행해보세요. 이 경우 코루틴은 메인 스레드에서도 실행됩니다.
코루틴은 비동기식으로 실행되고 스레드를 전환하고 일시 중단 및 재개할 수 있지만 결과를 예상했던 위치로 다시 반환할 수 있습니다. 이것을 가능하게 하는 마법은 무엇입니까? 그 비밀을 밝힐 때입니다.