-
[Coroutine] 코루틴 학습 - 3 (Coroutine Builders)Java/Kotlin 2022. 4. 27. 08:16반응형
Coroutine builders
- 일시중단 함수는 다른 일시중단 함수을 호출할 때 continuation 객체를 넘겨야 한다.
- 일시중단 함수 내에서 일반 함수를 호출할 수 있다.
- 일반 함수는 일시중단 함수를 호출할 수 없다.
- 즉, 모든 일시중단 함수는 다른 일시중단 함수에 의해 호출되어야 한다.
그렇다면 이 일시중단 함수를 최초에 호출할 때 누군가는 호출을 해야할텐데, 어디에서 호출이 가능할까?
- coroutine builder를 이용하면 일반 함수에서 일시중단 함수를 호출할 수 있도록 징검다리 역할을 해준다.
- kotlinx.coruotines 라이브러리에서 세 가지 coroutine builder를 지원한다.
- launch
- runBlocking
- async
launch builder
- launch는 개념상 새로운 쓰레드를 시작하여 동작하는 것과 유사하다.
- coroutine이 시작되면 독립적으로 동작을 수행한다.
fun main() { GlobalScope.launch { delay(1000L) println("World!") } GlobalScope.launch { delay(1000L) println("World!") } GlobalScope.launch { delay(1000L) println("World!") } println("Hello,") Thread.sleep(2000L) } // Hello, // (1 sec..) // World! // World! // World!
- launch 함수는 CoroutineScpoe 인터페이스의 확장 함수이다.
- CoroutineScope는 부모 코루틴과 자식 코루틴 간에 관계를 구축하기 위한 목적으로, structured concurrency라고 부르는 중요한 메커니즘이다.
- 예제 코드에서는 GlocalScope를 사용했지만 실제 프로젝트에서는 사용을 지양해야 한다. (그 이유는 나중에 포스팅할 예정)
- 예제 코드에서 코루틴의 delay 일시중단 함수가 끝나기 전에 main 함수가 종료되는 것을 방지하기 위해 Thread.sleep()을 호출하여 쓰레드를 잠시 sleep 시켜둔 것을 확인할 수 있다. delay 함수와 같은 일시중단 함수는 쓰레드를 블로킹하지 않기 때문에 메인 쓰레드가 종료되면 프로세스가 종료되어 버리기 때문이다.
- 이는 데몬 쓰레드를 생성하여 실행하는 모습과 비슷하지만, 코루틴은 쓰레드를 생성하여 실행하는 것보다 훨씬 비용이 저렴하다.
runBlocking builder
- launch builder 에서 살펴보았듯이 블로킹이 필요한 경우도 존재하는데, runBlocking을 이용하면 된다.
- runBlocking은 코루틴이 일시중단될 때마다 시작된 쓰레드를 블로킹한다.
- 다른 일반적인 유즈케이스는 단위 테스트에서 위와 동일한 이유로 쓰레드를 블로킹해야 할 때이다.
fun main() { runBlocking { delay(1000L) println("World!") } runBlocking { delay(1000L) println("World!") } runBlocking { delay(1000L) println("World!") } println("Hello,") } // (1 sec) // World! // (1 sec) // World! // (1 sec) // World! // Hello,
async builder
- async builder는 launch와 유사하지만, 값을 생산하여 반환하도록 설계되었다는 점에서 차이점이 있다.
- async 함수는 Deffered<T> 타입의 객체를 반환하는데, T 타입은 async 함수에 의해 생산되는 값의 타입이다.
- Deffered는 await()이라는 일시중단 함수를 가지고 있는데, 값을 반환할 준비가 되면 해당 값을 리턴하게 된다.
- async builder는 두 가지의 일을 동시에 병렬적 수행하여 데이터를 응답받을 때 종종 사용된다.
fun main() = runBlocking { val resultDeferred: Deferred<Int> = GlobalScope.async { delay(1000L) 200 } println("Before") val result: Int = resultDeferred.await() println("After") println(result) } // Before // (1 sec) // After // 200
참고자료
https://www.amazon.com/Kotlin-Coroutines-Deep-Marcin-Moskala/dp/8396395837
반응형'Java > Kotlin' 카테고리의 다른 글
[Coroutine] 코루틴 학습 - 6 (Job and children awaiting) (0) 2022.05.01 [Coroutine] 코루틴 학습 - 5 (Coroutine context) (0) 2022.04.28 [Coroutine] 코루틴 학습 - 4 (Structured Concurrency) (0) 2022.04.27 [Coroutine] 코루틴 학습 - 2 (Under the hood) (0) 2022.04.23 [Coroutine] 코루틴 학습 - 1 (Coroutine?) (0) 2022.04.16