Coroutine Context와

부모 코루틴 책임

부모 코루틴은 항상 자식이 완료되기를 기다립니다.

부모는 모든 자식의 실행을 명시적으로 추적하지 않고 모두 완료될 때까지 기다립니다.

일하다.

가입하다
사용할 필요가 없습니다

// launch a coroutine to process some kind of incoming request
val request = launch {
    repeat(3) { i -> // launch a few children jobs
        launch  {
            delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
            println("Coroutine $i is done")
        }
    }
    println("request: I'm done and I don't explicitly join my children that are still active")
}
request.join() // wait for completion of the request, including all its children
println("Now processing of the request is complete")

완전한 코드는 여기에서 찾을 수 있습니다

결과는 다음과 같습니다.

request: I'm done and I don't explicitly join my children that are still active
Coroutine 0 is done
Coroutine 1 is done
Coroutine 2 is done
Now processing of the request is complete


다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. 그러나 상위 범위 내에 있더라도 CoroutineScope(context: CoroutineContext) 함수에 의해 재정의되면 CoroutineScope는 다른 범위에서 시작된 작업이 완료될 때까지 기다리지 않습니다.

예를 들어 다음 코드를 살펴보겠습니다.

fun main() = runBlocking<Unit> {
    CoroutineScope(Dispatchers.IO).launch {
        delay(2000L)
        println("b")
    }

    launch {
        delay(1000L)
        println("a")
    }
}

이에 대한 출력은 다음과 같습니다.

a가 실행되는 순간 runBlocking 코루틴이 종료되고 상위 코루틴이 종료되며 별도의 범위에서 실행 중인 코루틴도 종료됩니다.

즉, 부모는 별도의 범위에 정의된 코루틴을 기다리지 않습니다.

a

Process finished with exit code 0

여기서 혼동해서는 안 되는 것은 CoroutineScope(Dispatcher.IO)에서 실행 중인 코루틴이 부모에 의해 취소되지 않는다는 것입니다.

main 함수가 끝에 도달하고 프로그램이 종료되고 중단됩니다.

아래 코드를 살펴보겠습니다.

다음 코드에서는 첫 번째 runBlocking이 종료되더라도 main 함수가 종료되지 않도록 main 함수 뒤에 또 다른 runBlocking을 배치합니다.

fun main() {
    runBlocking<Unit> {
        CoroutineScope(Dispatchers.IO).launch {
            delay(2000L)
            println("b")
        }

        launch {
            delay(1000L)
            println("a")
        }
    }

    runBlocking {
        delay(3000L)
    }
}

이 코드의 출력은 다음과 같습니다.

CoroutineScope(Dispatcher.IO)에서 코루틴을 실행한 결과 “b”가 출력되는 것을 볼 수 있습니다.

a
b

Process finished with exit code 0


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 코루틴 컨텍스트 및 디스패처 – 부모의 책임

원본 텍스트의 최종 편집: 2022년 6월 27일


디버깅을 위한 코루틴 명명

자동 구성된 ID는 코루틴이 자주 기록되고 동일한 코루틴에서 생성된 관련 로그 레코드만 상호 연관시켜야 할 때 유용합니다.

그러나 코루틴이 특정 요청을 하거나 특정 백그라운드 작업을 수행하는 경우 디버깅 목적으로 이름을 설정하는 것이 좋습니다.

컨텍스트 요소 코루틴 이름스레드 이름과 같은 용도로 사용됩니다.

이는 디버깅 모드가 활성화되었을 때 코루틴을 실행하는 스레드의 이름에 포함됩니다.

다음 예제는 이 개념을 보여줍니다.

log("Started main coroutine")
// run two background value computations
val v1 = async(CoroutineName("v1coroutine")) {
    delay(500)
    log("Computing v1")
    252
}
val v2 = async(CoroutineName("v2coroutine")) {
    delay(1000)
    log("Computing v2")
    6
}
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")

완전한 코드는 여기에서 찾을 수 있습니다

JVM 옵션에서 -Dkotlinx.coroutines.debug *1을 입력하면 생성된 결과는 다음과 유사합니다.

(main @main#1) Started main coroutine
(main @v1coroutine#2) Computing v1
(main @v2coroutine#3) Computing v2
(main @main#1) The answer for v1 / v2 = 42

다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. -Dkotlinx.coroutines.debug를 입력하지 않으면 다음과 같은 결과가 표시됩니다.

(main) Started main coroutine
(main) Computing v1
(main) Computing v2
(main) The answer for v1 / v2 = 42

-Dkotlinx.coroutines.debug 설정 방법 다음 포스트보자


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 코루틴 컨텍스트 및 디스패처 – 디버깅을 위한 코루틴 이름 지정

원본 텍스트의 최종 편집: 2022년 6월 27일


컨텍스트 요소 결합

때로는 코루틴 컨텍스트에서 여러 항목을 정의해야 할 수도 있습니다.

이를 위해 + 연산자를 사용할 수 있습니다*1. 예를 들어 디스패처를 명시적으로 지정하고 동시에 명시적으로 명명된 코루틴을 실행해야 할 수 있습니다.

launch(Dispatchers.Default + CoroutineName("test")) {
    println("I'm working in thread ${Thread.currentThread().name}")
}

완전한 코드는 여기에서 찾을 수 있습니다

-JVM 옵션*2에 Dkotlinx.coroutines.debug 추가 코드의 결과는 다음과 같습니다.

I'm working in thread DefaultDispatcher-worker-1 @test#2

다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. Coroutine Context가 + 연산자와 결합될 수 있는 이유는 Fun plus 연산자가 CoroutineContext에 정의되어 있기 때문입니다.

    public operator fun plus(context: CoroutineContext): CoroutineContext =
        ...

*2. JVM 옵션 설정 방법 다음 포스트참조하십시오


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 코루틴 컨텍스트 및 디스패처 – 컨텍스트 요소 결합

원본 텍스트의 최종 편집: 2022년 6월 27일