본문 바로가기

[Kotlin] 코루틴 #3 - suspend Function (중단함수)

코루틴 #3 - suspend Function (중단함수)

중단 함수(Suspending Function) 와 일반 함수(Sequential function)

 

Coroutine 이전 글

  1. 코루틴 #1 - 기본
  2. 코루틴 #2 - CoroutineContext와 CoroutineScope란?

 

 

기본 순차 실행 (Sequential by Default)

기본적으로 Code & Function은 순차적(Sequential)으로 수행

이런 개념은 Coroutine 내부에서도 동일하게 적용됩니다

 

일정시간 delay 후 Integer 값을 반환하는 두개의 suspend(중단) 함수 생성 

suspend fun testOne(): Int {
    delay(1000)			// 1초 대기
    return 20			// 20 반환
}

suspend fun testTwo(): Int {
    delay(2000)			// 2초 대기
    return 40			// 40 반환
}

 

두 개의 suspend함수 호출 후 걸리는 시간을 보기위한 예시

fun main(args: Array<String>) = runBlocking<Unit> {
    val time = measureTimeMillis {		// measureTimeMillis 블록 내부 실행에 걸리는 시간 반환
        val one = testOne()		// suspend 함수 1
        val two = testTwo()		// suspend 함수 2
        println("Result is one [$one] two [$two]")
    }
    println("Completed in ${time}ms")		// 총 걸린 시간 표시
}

위 예시 코드는 두 개의 중단함수 testOne(), testTwo()를 순차적으로 호출하여, 반환된 값을 더하여 출력하는 예시입니다

출력 결과

Result is one [20] two [40]
Completed in 3016ms


결과에서 총 수행시간을 보면 함수가 순차적으로 수행되었기 때문에 3016ms가 걸렸습니다.

먼저 testOne()이 1000ms대기 후 완료되고, 그 다음 testTwo()가 2000ms를 Delay하기 때문에 그렇습니다

 

async 통한 동시 수행 (Concurrent using async)

만약 위의 두 중단함수가 서로 인과관계(의존성)을 갖지 않는다면, 두 개의 함수를 동시에 수행시 더 빠른 동작을 구현 가능

launch{}async{}는 동일한 컨셉이지만, return 객체의 차이가 있는 코루틴 빌더입니다.

   launch{} -> Job return
   async{} -> Deferred<T> return

Job은 launch로 생성된 코루틴의 상태를 관리하는 용도로 사용하고 결과값을 리턴받을 수 없으나,

Deferred는 async블럭 내 수행된 결과를 원하는 시점에 return받을 수 있다는 큰 차이가 있습니다.

 Deferred는 job을 상속받아 구현되었기 때문에 Job의 기능을 사용할 수 있습니다.

fun main(args: Array<String>) = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async { testOne() }
        val two = async { testTwo() }
        println("Result is one [${one.await()}] two [${two.await()}]")
    }
    println("Completed in $time ms")
}


출력결과

Result is one [20] two [40]
Completed in 2059ms


두 개의 작업이 동시에 실행되었기 때문에 testTwo()의 delay(2000)을 마지막으로 모든 실행이 종료된 걸 확인 가능

 

async의 지연 실행 (Lazily started async)

launch와 마찬가지로 async도 start 파라미터에 CoroutineStart.LAZY 값을 할당해서 실행지연 가능

LAZY옵션이 설정된 코루틴은 start() 또는 join()/await() 함수가 호출되는 시점에 실행이 됩니다.

fun main(args: Array<String>) = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async(start = CoroutineStart.LAZY) { testOne() }
        val two = async(start = CoroutineStart.LAZY) { testTwo() }

        delay(4000)
	// LAZY 설정 코루틴 실행 시작
        one.start()
        two.start()

        println("Result is one [${one.await()}] two [${two.await()}]")
    }
    println("Completed in $time ms")
}

실행결과

Result is one [20] two [40]
Completed in 6020ms

걸린 시간을 보면 6020ms로 기존 2059ms에 비해 4000ms가 길어졌다는 걸 보면

testOne() 과 testTwo() 중단함수의 실행이 delay(4000) 이후에 시작되고 반환되는 것을 보여줍니다.

LAZY 설정 코루틴은 꼭 start()가 아닌 await()으로도 대체 가능하기 때문에 위 예시에서 one.start() two.start()는 생략이 가능합니다