ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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

    반응형

    댓글

Designed by Tistory.