KOTLIN

[KOTLIN] SUSPEND 함수

집한구석 2022. 6. 6. 12:33
728x90

Suspend

  • 비동기 실행을 위한 중단 지점
  • 잠시 중단하고, 언젠가 다시 시작 즉 일시중단이 가능하도록 하게 하는 키워드

코루틴 Suspend 함수는 구성 및 접근법이 다양함


순차적 실행

fun main() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = doOne();
        val two = doTwo();

        println("결과 : ${one + two}")
    }
    println("완료 ${time}")
}

suspend fun doOne(): Int {
    println("첫번째 함수 시작")
    delay(1000L)
    return 1;
}

suspend fun doTwo(): Int {
    println("두번째 함수 시작")
    delay(1000L)
    return 2;
}
// 첫번째 함수 시작
// 두번째 함수 시작
// 결과 : 3
// 완료 2024
  • 코루틴 내부 코드는 일반 코드처럼 순서대로 실행 
  • 비동기 연산을 순차적으로 실행함 

동시 실행

fun main() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async { doUseOne() }
        val two = async { doUseTwo() }

        println("결과 : ${one.await() + two.await()}")
    }
    println("완료 ${time}")
}

suspend fun doUseOne(): Int {
    println("첫번째 함수 시작")
    delay(1000L)
    return 1;
}

suspend fun doUseTwo(): Int {
    println("두번째 함수 시작")
    delay(1000L)
    return 2;
}

// 첫번째 함수 시작
// 두번째 함수 시작
// 결과 : 3
// 완료시간 : 1040
  • 동시 수행시 async를 사용
  • async는 launch랑 비슷한 코루틴 빌더, deffered(결과값을 나중에 돌려줌) 객체를 반환함
  • await() 함수를 사용하면 비동기 처리 완료됐을 때 결과값을 반환받을 수 있음
  • 예제를 확인해보면 완료시간이 2초가아니라 1초만에 처리함

지연 실행

fun main() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async(start = CoroutineStart.LAZY) { doUseOne() }
        val two = async(start = CoroutineStart.LAZY) { doUseTwo() }
		//one.start()
        //two.start() 
        //스타트를 하지 않은 경우 완료시간이 2초이지만, 할경우 1초만에 처리됨
        println("결과 : ${one.await() + two.await()}")
    }
    println("완료시간 : ${time}")
}

suspend fun doUseOne(): Int {
    println("첫번째 함수 시작")
    delay(1000L)
    return 1;
}

suspend fun doUseTwo(): Int {
    println("두번째 함수 시작")
    delay(1000L)
    return 2;
}

// 첫번째 함수 시작
// 두번째 함수 시작
// 결과 : 3
// 완료시간 : 2033
  • async로 생성된 코루틴은 start = CoroutineStart.Lazy 옵션을 주게되는 경우 지연실행이 됨
  • suspending 함수가 사용되는 경우 lazy대신 CoroutineStart.Lazy 옵션 사용
  • start를 선언할 경우 동시에 처리 실행하기 때문에 완료시간이 1초 걸림 

Async-style 함수형태 실행

fun main() {
    val time = measureTimeMillis {
        val one = doUsefulOneAsync()
        val two = doUsefulTwoAsync()

        runBlocking {
            println("결과 : ${one.await() + two.await()}")
        }

    }
    println("완료시간 : ${time}")
}

fun doUsefulOneAsync() = GlobalScope.async { doUsefulOne() }
fun doUsefulTwoAsync() = GlobalScope.async { doUsefulTwo() }

suspend fun doUsefulOne(): Int {
    println("첫번째 함수 시작")
    delay(1000L)
    return 1;
}

suspend fun doUsefulTwo(): Int {
    println("두번째 함수 시작")
    delay(1000L)
    return 2;
}
  • GlobalScope 범위에서 async 빌더를 통하여 비동기적으로 작동하는 함수를 정의가 가능함
  • async함수는 suspending이 아니라 어디서든지 사용가능하나, 실제동작은 비동기로 이루어짐
  • 이방식은 권장하지 않음, async함수와 await사이에 excedption이 발생한 경우, 중단되었음에도 불구하고 연산을 수행하기 때문

Structured 동시성 / 비동기 실행

fun main() = runBlocking {
    val time = measureTimeMillis {
        println("결과 : ${concurrentUse()}")
    }
    println("완료시간 : ${time}")
}

suspend fun concurrentUse(): Int = coroutineScope {
    val one = async { getOne() }
    val two = async { getTwo() }
//    delay(10)
//    kotlin.io.println("예외")
//    throw Exception()
//    예외발생시 함수 실행이 중단됨
    one.await() + two.await()
}

suspend fun getOne(): Int {
    println("첫번째 함수 시작")
    delay(1000L)
    return 1;
}

suspend fun getTwo(): Int {
    println("두번째 함수 시작")
    delay(1000L)
    return 2;
}
  • 동시성 처리 함수를 coroutineScope안에서만 처리하도록 설정
  • coroutineScope안에만 있기 때문에 예외발생시, 연산을 진행하지 않음 

'KOTLIN' 카테고리의 다른 글

[KOTLIN] CONTEXT / DISPATCHER  (0) 2022.06.15
[KOTLIN] CANCELLATION (취소)  (0) 2022.06.09
[KOTLIN] 코루틴  (0) 2022.06.01
[KOTLIN] NULL SAFTY / NULL 처리방법  (0) 2022.05.30
[KOTLIN] LATEINIT / LAZY  (0) 2022.05.22