[Kotlin] 코루틴(coroutine)을 통한 비동기 처리 설명 & 예제

728x90

 

코틀린에서 비동기 처리로 여러개의 루틴을 동시에 처리할 수 있는 방법

  • 메인의 동기처리와 별도로 움직이며 개발자가 제어 가능한 루틴 처리

  • import kotlinx.coroutines.* import 필수
  • 코르틴은 제어범위 및 실행범위를 지정할 수 있다 -> 코루틴의 Scope
    1. Global Scope
      • 프로그램 어디서나 제어, 동작이 가능한 기본범위
    2. CoroutineScope
      • 특정한 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위
        • 모든 플랫폼에서 지원되는 것은 아님, 지원되는 플랫폼에 따라서 사용
          1. Dispatchers.Default(기본적인 백그라운드 동작)
          2. Dispatchers.IO(I/O에 최적화 된 동작)
          3. Dispatchers.Main메인(UI) 스레드에서 동작

Scope에서 제어되도록 코루틴 생성

launch vs async

코루틴에서의 반환값이 있는지의 여부에 따라 나뉨

  • launch : 반환값이 없는 Job 객체
  • async : 반환값이 있는 Deffered 객체(마지막 값 Return)
  • 모두 람다함수의 형태
    예제

  • 아래 예제에서 아무값이 출력되지 않는 건 실행과 동시에 바로 종료 되기 때문에 코루틴이 실행되지 못한것(기다리지 못한 것)
    따라서 코루틴이 끝까지 실행되는 것을 보장하기 위해서는 일정한 범위내에서 기다려주어야 한다.
import kotlinx.coroutines.*

fun main() {

    val scope = GlobalScope

    scope.launch {
        for(i in 1..5) {
            println(i)
        }
    }
}
  • 이럴 떄는 runBlocking 블럭을 만들고 launch, async를 넣어 준다
    • 코루틴이 종료 될떄까지 메인 루틴을 잠시 대기 시켜준다
      • 안드로이드에서는 메인 스레드에서 runBlocking을 걸어주면 일정시간 이상 응답이 없는 경우 ANR(Application Not Responding) : 응답 오류 발생 -> 강제종료됨
import kotlinx.coroutines.*

fun main() {

    runBlocking {
        launch {
            for(i in 1..5) {
                println(i)
            }
        }
    }
}

루틴의 대기를 위한 추가적 함수들 (delay(), join(), await())

아래의 함수들은 코루틴 내부 또는 runBlocking{}과 같은 루틴의 대기가 가능한 구문 안에서만 동작 가능

  1. delay(milisecond: Long)
    • milisecond 단위로 루틴을 잠시 대기시키는 함수
  2. Job.join()
    • Job의 실행이 끝날때까지 대기하는 함수
  3. Deferred.await()
    • Deferred의 실행이 끝날때까지 대기하는 함수
    • Deferred의 결과도 반환

예제

import kotlinx.coroutines.*

fun main() {

    runBlocking {
        var a = launch {
            for(i in 1..5) {
                println(i)
                delay(10)
            }
        }

        //새로운 Deferred 객체 생성
        val b = async {
            "async 종료"
        }

           println("async 대기")
        println(b.await())

        println("launch 대기")
        a.join()
        println("launch 종료")
    }
}

 

코루틴 실행 도중 중단하는 방법

  • cancel()
    • 코루틴에 cancel() 걸어주면 두가지 조건 발생 , 코루틴 중단
      1. 코루틴 내부의 delay() 함수 또는 yield() 함수가 사용된 위치까지 수행된 뒤 종료됨
      2. cancel()로 인해 속성인 isActive가 false가 되므로 이를 확인하여 수동으로 종료함
import kotlinx.coroutines.*

fun main() {

    runBlocking {
        var a = launch {
            for(i in 1..5) {
                println(i)
                delay(10)
            }
        }

        //새로운 Deferred 객체 생성
        val b = async {
            "async 종료"
        }

           println("async 대기")
        println(b.await())

        println("launch 취소")
        a.cancel()
        println("launch 종료")
    }
}

withTimeoutOrNull()

제한시간 내에 수행되면 결과값을, 아닌경우 null 반환

  • join 이나 await 처럼 Blocking 함수임
import kotlinx.coroutines.*

fun main() {

    runBlocking {
        var result = withTimeoutOrNull(50) {
            for (i in 1..10) {
                println(i)
                delay(10)
            }
            "Finish"
        }
        println(result)
    }
}

 

728x90

댓글

Designed by JB FACTORY