티스토리 뷰

이 요약은 https://youtu.be/Lpieg1zrKdg 다음 영상을 보고 요약한 개념입니다.

  • 여러 개의 루틴을 동시에 실행하여 결과를 내고 싶다면 비동기 처리를 지원하는 코루틴을 사용한다.
  • 코루틴은 메인이 되는 루틴과 별도로 진행이 가능한 루틴으로 코루틴은 개발자가 실행과 종료를 마음대로 제어할 수 있는 단위이다.
  • 코루틴은 제어 범위와 실행 범위를 지정할 수 있다.

코루틴의 Scope

GlobalScope

프로그램 어디서나 제어, 동작이 가능한 기본 범위

CoroutineScope

특정한 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위

Coroutine의 dispatcher

  1. Dispatcher.Default : 기본적인 백그라운드에서 동작
  2. Dispatcher.IO : 네트워크나 디스크에 사용하는 I/O에 최적화 된 동작
  3. Dispatcher.Main : 메인(UI) 스레드에서 동작

launch와 async

  • 생성된 Scope를 launch나 async 함수를 활용하여 새로운 Coroutine를 생성할 수 있다.
  • launch와 async의 차이는 반환값이 있는지에 대한 여부

launch

launch {
    for (i in 1..10) {
        println(i)
    }
}
  • 반환값이 없는 Job 객체를 반환한다.

async

async {
    var sum = 0
    for (i in 1..10) {
        sum ++
    }
    sum // 마지막 값이 반환된다.
}
  • 반환값이 있는 Deffered 객체를 반환한다.
  • aynch에 사용되는 람다 함수의 마지막 구문이 반환된다.

실습

import kotlinx.coroutines.* // coroutine 관련 라이브러리를 import

fun main() {
    val scope = GlobalScope

    scope.launch {
        for (i in 1..5) {
            println(i)
        }
    } // 이 scope에서 동작하기 전에
    // main 함수가 끝나게 되어 코루틴도 같이 종료된다.
}

// 실행결과
// 결과값이 나오지 않는다.
  • 코루틴은 제어되는 스코프 또는 프로그램 전체가 종료되면 함께 종료된다.
  • 그래서 코루틴이 끝까지 실행되는 것을 보장하려면 일정한 범위에서 코루틴이 모두 실행될 때까지 잠시 기다려줘야 한다.
import kotlinx.coroutines.*

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


// 실행결과
1
2
3
4
5
  • runBlocking 블록을 만들고 이 블록 안에서 launch나 async를 직접 실행하면 코루틴이 종료될 때까지 메인 루틴을 잠시 대기시켜준다.
  • 안드로이드에서 주의할 점은 메인 스레드에서 runBlocking을 걸어주면 ANR이 발생하여 앱이 강제 종료될 가능성이 있다.

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

밑의 세 함수들은 코루틴 내부 또는 runBlocking 블록과 같은 루틴의 대기가 가능한 구문 안에서만 사용이 가능하다.

1. delay(milisecond: Long)

  • milisecond 단위로 루틴을 잠시 대기시키는 함수

2. join()

  • Job.join() 형태로 쓰이며 Job의 실행이 끝날때까지 대기하는 함수

3. await()

  • Defferred.await() 형태로 쓰이며 Defferred의 실행이 끝날때까지 대기하는 함수
  • Defferred의 결과도 반환함
 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 종료")
     }
 }

 // 실행결과
 async 대기
 1
 async 종료
 launch 대기
 2
 3
 4
 5
 launch 종료

코루틴 도중 중단

cancel()

  • 코루틴에 cancel을 걸어주면 다음 두 가지 조건이 발생하며 코루틴을 중단시킬 수 있다.
    • 코루틴 내부의 delay() 함수 또는 yield() 함수가 사용된 위치까지 수행된 뒤 종료
    • cancel() 로 인해 속성인 isActive가 false가 되므로 이를 확인하여 수동으로 종료
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 종료")
    }
}

// 실행결과
async 대기
1
async 종료
launch 취소
launch 종료

withTimeoutOrNull()

  • 제한 시간 내에 수행되면 결괏값을 아닌 경우 null을 반환하는 함수
  • join()이나 await()과 같은 blocking 함수
import kotlinx.coroutines.*

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

        println(result)
    }
}

// 실행결과
1
2
3
null //    timeOut 내에 수행될 수 없어 null이 출력된다.

출처

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함