Dev_TIMI

[Kotlin] Coroutine - async()

by its_TIMI

여러 외부 자원을 동시에 호출해야 하는 상황에서 유용하게 활용될 수 있는 함 수 .....

 

요약 : 두 가지의 활용 예시와 주의사항.

 

두 코드 예시의 실행 시간 차이를 이해하기 위해, 각각의 동작 방식을 살펴보겠습니다.

첫 번째 코드 예시

package coroutine

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main(): Unit = runBlocking {

    val time = measureTimeMillis {
        val job1 = async { apiCall1() }
        val job2 = async { apiCall2(job1.await()) }

        printWithThread( job2.await())
    }

    printWithThread("소요시간 : $time ms ")
}

suspend fun apiCall1(): Int {
    delay(1_000L)
    return 1
}suspend fun apiCall2(num: Int): Int {
    delay(1_000L)
    return num + 2
}
[main @coroutine#1] 3
[main @coroutine#1] 소요시간 : 2039 ms 

Process finished with exit code 0

 

 

동작 방식:

  • job1은 apiCall1() 함수를 비동기적으로 실행합니다. 이 함수는 1초의 지연 후 1을 반환합니다.
  • job2는 apiCall2() 함수를 비동기적으로 실행합니다. 하지만 이 함수는 job1.await()를 호출하여 job1의 결과를 기다립니다. 따라서 job2는 job1이 완료될 때까지 시작되지 않습니다.
  • job1과 job2는 연속적으로 실행됩니다. 즉, 두 함수의 실행 시간이 합쳐져서 총 2초가 소요됩니다.

두 번째 코드 예시

package coroutine

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main(): Unit = runBlocking {

    val time = measureTimeMillis {
        val job1 = async { apiCall1() }
        val job2 = async { apiCall2() }

        printWithThread(job1.await() + job2.await())
    }

    printWithThread("소요시간 : $time ms ")
}

suspend fun apiCall1(): Int {
    delay(1_000L)
    return 1
}suspend fun apiCall2(): Int {
    delay(1_000L)
    return 2
}
[main @coroutine#1] 3
[main @coroutine#1] 소요시간 : 1028 ms 

Process finished with exit code 0

 

동작 방식:

  • job1과 job2는 각각 apiCall1()과 apiCall2() 함수를 독립적으로 비동기적으로 실행합니다.
  • 두 함수 모두 각각 1초의 지연을 가지고 있지만, 동시에 실행되므로 전체 실행 시간은 대략 1초입니다.
  • await() 호출은 각 작업의 완료를 기다리지만, 두 작업이 병렬적으로 실행되므로, 전체 소요 시간은 두 함수 중 가장 긴 시간에 근접합니다.

 

 

결론

첫 번째 코드는 job2가 job1의 결과를 기다리므로 연속적으로 실행되어 총 2초가 걸립니다. 반면에 두 번째 코드에서는 job1과 job2가 동시에 실행되어 전체 소요 시간이 대략 1초가 됩니다. 이러한 차이는 코루틴의 비동기 실행 방식과 await() 함수의 사용 방식에 의해 결정됩니다.

 

 

주의사항

CoroutineStart.LAZY 옵션을 사용하면, await() 함수를 호출했을 때에야 실행을 시작하고, 계산 결과를 계속 기다린다. 

 

다시 말하자면 val job1, val job2 가 써있는 줄까지는 실행되지 않고 객체만 각각 할당되어있다가 

 

job1.await() 부분에서 job1에 담겨있는 객체가 실행상태로 바뀌고,

계산 결과가 나오면 job2.await()으로 넘어가고 그 때서야 job2에 있는 객체가 실행 상태로 바뀌는 것이다.

 

따라서 그냥 이렇게 쓰면 왕오래걸림!

package coroutine

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main(): Unit = runBlocking {

    val time = measureTimeMillis {
        val job1 = async(start = CoroutineStart.LAZY) { apiCall1() }
        val job2 = async(start = CoroutineStart.LAZY) { apiCall2() }

        printWithThread(job1.await() + job2.await())
    }

    printWithThread("소요시간 : $time ms ")
}

suspend fun apiCall1(): Int {
    delay(1_000L)
    return 1
}suspend fun apiCall2(): Int {
    delay(1_000L)
    return 2
}
[main @coroutine#1] 3
[main @coroutine#1] 소요시간 : 2037 ms 

Process finished with exit code 0

 

 

하쥐만,,,

 

CoroutineStart.LAZY 옵션을 사용할 때 async()를 할당한 job1.start()라던지? 처리를 해놓으면 ㄱㅊ.

 

package coroutine

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main(): Unit = runBlocking {

    val time = measureTimeMillis {
        val job1 = async(start = CoroutineStart.LAZY) { apiCall1() }
        val job2 = async(start = CoroutineStart.LAZY) { apiCall2() }

        job1.start()
        job2.start()
        
        printWithThread(job1.await() + job2.await())
    }

    printWithThread("소요시간 : $time ms ")
}

suspend fun apiCall1(): Int {
    delay(1_000L)
    return 1
}suspend fun apiCall2(): Int {
    delay(1_000L)
    return 2
}
[main @coroutine#1] 3
[main @coroutine#1] 소요시간 : 1032 ms 

Process finished with exit code 0

 

반응형

'Kotlin' 카테고리의 다른 글

[Kotlin] Coroutine - Structured Concurrency  (0) 2024.01.12
[Kotlin] Coroutine의 예외처리  (0) 2024.01.12
[Kotlin] Coroutine - 취소  (0) 2024.01.11
[Kotlin] Coroutine 디버깅 옵션  (1) 2024.01.09
람다 그리고 코틀린  (0) 2023.12.20

블로그의 정보

Dev_TIMI

its_TIMI

활동하기