경험의 기록

여러개의 구문을 동시에 실행하고 싶다면 코루틴을 사용해야한다.

 

코루틴의 Scope

코루틴은 제어범위 및 실행범위를 지정할 수 있다.

  • GlobalScope : 프로그램 어디서나 동작,제어가 가능한 기본 범위
  • CoroutineScope : 특정 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위

 

CoroutineScope 를 사용할 때 적용가능한 Dispatcher

  • Dispatchers.Default : 기본적인 백그라운드 동작
  • Dispatchers.IO : I/O 최적화 동작
  • Dispatchers.Main : 메인 스레드 동작

 

launch, async

생성된 스코프에서 launch와 async를 사용하여 코루틴을 생성할 수 있다.

launch 는 반환값이 없으며 (Job)

async 는 반환값이 존재한다. (Deferred)


코루틴 사용하기

dependency 추가

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5"

gradle 의 dependency에 추가해준다.

 

그 후

import kotlinx.coroutines.*

를 import 해주면 코루틴을 사용할 수 있다.

 

import kotlinx.coroutines.*

fun main(args:Array<String>){

    val scope = GlobalScope

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

코루틴을 사용하는 예시인데, 코루틴은 프로그램이 종료되거나 제어되는 스코프가 종료되면 같이 종료되므로

이 예시에서는 별다른 함수가 없으므로 println을 하기전에 프로그램이 종료된다.

 

코루틴 대기함수

코루틴이 확실하게 작동하게 하기 위하여 runBlocking 을 사용할 수 있는데,

import kotlinx.coroutines.*

fun main(args:Array<String>){

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

코루틴이 종료될때 까지 메인 루틴을 대기시킨다.

하지만 runBlocking 는 코루틴이 스레드를 혼자 점유하게 되고 일정시간 응답이 없으면 ANR 오류가 발생하여 앱이 종료되므로 주의해야한다.

 

루틴의 대기를 위한 추가적인 함수로 

delay, join, await 가 있다.

  • delay() : milisecond 단위로 루틴 대기
  • join() : Job의 실행이 끝날 때 까지 대기 (launch)
  • await() : deferred의 실행이 끝날 때 까지 대기, 결과값 반환 (async)
import kotlinx.coroutines.*

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

        val b = async{
            "async 종료"
        }

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

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

await에서 async 종료까지 대기시킨 후, 반환값을 받아 출력한 것을 확인할 수 있으며 join에서 launch가 끝날 때 까지 대기 시킨 후 종료를 출력하는 것을 확인할 수 있다.

 

코루틴 취소함수

cancel 를 이용하여 루틴을 취소할 수 있다.

import kotlinx.coroutines.*

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

        val b = async{
            "async 종료"
        }

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

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

또한 withTimeoutOrNull 을 사용하여

제한시간 내에 수행되면 결과값을, 아니면 null을 반환 받을 수도 있는데

 

import kotlinx.coroutines.*

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

딜레이를 넣지 않았을경우 Finish를 출력하지만

딜레이를 넣었을 때,

import kotlinx.coroutines.*

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

시간내에 다 실행되지 못하고 null이 출력되는 것을 확인할 수 있다.

 

 


 

참조 : www.youtube.com/watch?v=Lpieg1zrKdg

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading