관리 메뉴

피터의 개발이야기

[kotlin] 코틀린 코루틴의 정석 - CoroutineScope의 start 옵션 본문

Programming/Kotlin

[kotlin] 코틀린 코루틴의 정석 - CoroutineScope의 start 옵션

기록하는 백앤드개발자 2024. 6. 10. 10:32
반응형

ㅁ 들어가며

 코틀린 코루틴의 정석 책을 보고 정리한 글입니다.

11장 코루틴의 심화 - CoroutineScope의 start 옵션

ㅇ launch나 async 코루틴 빌더 함수에 CoroutineStart옵션을 지정하여 다양한 코루틴의 실행 방법을 지정할 수 있다.

 

ㅇ CoroutineStart 옵션

  ㄴ CoroutineStart.DEFAULT

  ㄴ CoroutineStart.LAZY

  ㄴ CoroutineStart.ATOMIC

  ㄴ CoroutineStart.UNDISPATCHED

 

ㅁ CoroutineStart.DEFAULT

ㅇ launch의 start의 기본 값은 DEFAULT이다. 

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  launch {
    println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] 코루틴의 실행을 CoroutineDispathcer에 할당")
  }
  println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] 코루틴 빌더를 호출한 코루틴은 계속해서 실행")
}
/*
[main @coroutine#1][지난 시간: 2ms] 코루틴 빌더를 호출한 코루틴은 계속해서 실행
[main @coroutine#2][지난 시간: 18ms] 코루틴의 실행을 CoroutineDispathcer에 할당
*/

ㅇ CoroutineStart.DEFAULT으로 설정하면 코루틴 빌더는 즉시 생성된 코루틴의 실행을 CoroutineDispathcer에 할당하며, 코루틴 빌더를 호출한 코루틴은 계속해서 실행된다.

ㅇ 기존 메인 코루틴이 main 스레드에서 실행되고, 이 메인 스레드가 완료되어 양보하면 CoroutineDispathcer에 할당된 코루틴이 실행되는 일반적인 동작 방식이다.

 

ㅁ CoroutineStart.ATOMIC

ㅇ CoroutineStart.ATOMIC 선언부의 주석을 해석하였다.

Atomically (i.e., in a non-ancellable way) schedules the coroutine for execution according to its context.
This is similar to DEFAULT, but the coroutine cannot be cancelled before it starts executing.
Cancellability of coroutine at suspension points depends on the particular implementation details of suspending functions as in DEFAULT.
원자적으로(즉, 취소할 수 없는 방식으로) 컨텍스트에 따라 코루틴 실행을 예약합니다. 이는 DEFAULT와 유사하지만 코루틴이 실행을 시작하기 전에 취소할 수 없습니다.
정지 지점에서 코루틴을 취소할 수 있는지 여부는 DEFAULT와 같이 정지 함수의 특정 구현 세부 사항에 따라 달라집니다.

ㅇ 정리하면, CoroutineStart.ATOMIC 옵션은 코루틴의 취소를 방지하는 옵션이다.

 

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  val job = launch(start = CoroutineStart.DEFAULT) {
    println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] 취소로 인해 이 로그는 보이지 않는다.")
  }
  job.cancel()
  println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] DEFAULT 메인 코루틴이 실행되지만...")

  val job2 = launch(start = CoroutineStart.ATOMIC) {
    println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] ATOMIC 옵션은 코루틴의 취소를 방지하는 옵션이다.")
  }
  job2.cancel()
  println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] ATOMIC 메인 코루틴이 실행되며,")
}
/*
[main @coroutine#1][지난 시간: 7ms] DEFAULT 메인 코루틴이 실행되지만...
[main @coroutine#1][지난 시간: 25ms] ATOMIC 메인 코루틴이 실행되며,
[main @coroutine#3][지난 시간: 76ms] ATOMIC 옵션은 코루틴의 취소를 방지하는 옵션이다.
*/

ㅇ DEFAULT의 job은 취소가 되었지만, ATOMIC의 job은 취소가 되지 않았다. 

 

ㅁ CoroutineStart.UNDISPATCHED

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  launch(start = CoroutineStart.DEFAULT) {
    println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] Dispatch에 의해 나중에 실행")
  }

  launch(start = CoroutineStart.UNDISPATCHED) {
    println("[${Thread.currentThread().name}][${getElapsedTime(startTime)}] UNDISPATCHED는 바로 실행되고,")
  }
}
/*
[main @coroutine#3][지난 시간: 8ms] UNDISPATCHED는 바로 실행되고,
[main @coroutine#2][지난 시간: 25ms] Dispatch에 의해 나중에 실행
*/

ㅇ CoroutineStart.UNDISPATCHED옵션은 코루틴 빌더를 호출한 스레드에서 코루틴이 즉시 실행되도록 한다.

 

ㅁ CoroutineStart.LAZY

LAZY 선언부의 주석, 지연실행으로 비동기 Job들의 실행과 취소를 능동적으로 관리할 수 있다

 

fun main() = runBlocking<Unit> {
  val batchJob: Job = launch(start = CoroutineStart.LAZY) {
    println("[${Thread.currentThread().name}] 배치작업 실행")
  }
  println("[${Thread.currentThread().name}] 메인작업 실행")
  delay(1000L) // 1초간 대기
  batchJob.start() // 코루틴 실행
}
/* 출력
[main @coroutine#1] 메인작업 실행
[main @coroutine#2] 배치작업 실행
*/

ㅇ CoroutineStart.Lazy가 아니면 다른 옵션은 자동으로 실행 상태가 된다.

ㅇ 작업 중에 우선 순위가 낮고 오래 걸리는 배치성 업무가 있을 수 있다.
ㅇ 서비스 지연을 예방하기 위해 메인작업 이후에 실행시킬 수 있다.
ㅇ LAZY로 정의된 루틴은 start()로 실행된다.

ㅇ 코루틴 빌더는 코루틴을 추상화하나 Job 객체를 통해 코루틴의 상태를 추적하고 일시 중단 및 재실행을 할 수 있다.

   ㄴ 관련 자세한 글은 [kotlin] 코틀린 코루틴의 정석- 빌더와 Job에 정리되었다.

 

ㅁ 함께 보면 좋은 사이트

 조세영 - 코틀린 코루틴의 정석

반응형
Comments