Coroutine Context와

스위치 스레드

JVM 옵션에 -Dkotlinx.coroutines.debug를 넣어 다음 코드를 실행해 보겠습니다(디버그 확인).

newSingleThreadContext("Ctx1").use { ctx1 ->
    newSingleThreadContext("Ctx2").use { ctx2 ->
        runBlocking(ctx1) {
            log("Started in ctx1")
            withContext(ctx2) {
                log("Working in ctx2")
            }
            log("Back to ctx1")
        }
    }
}

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

그것은 몇 가지 새로운 기술을 보여줍니다. 하나는 실행 차단명시적으로 인스턴스화된 컨텍스트가 있고 다른 하나는 다음 출력에서 ​​볼 수 있는 것과 같습니다. 맥락과 함께 동일한 코루틴을 유지하면서 함수를 사용하여 컨텍스트를 변경할 수 있습니다.

(Ctx1 @coroutine#1) Started in ctx1
(Ctx2 @coroutine#1) Working in ctx2
(Ctx1 @coroutine#1) Back to ctx1

또한 이 예에서 Kotlin 표준 라이브러리는 사용 기능 newSingleThreadContext더 이상 필요하지 않을 때 생성된 스레드를 해제하는 데 사용됩니다.


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

원래의: 코루틴 컨텍스트 및 디스패처 – 스레드 간 점프

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


상황에 맞는 직업

코루틴의 작업은 Context, coroutineContext(Job)*1의 구성 요소입니다. 식에서 얻을 수 있습니다.

fun main() = runBlocking<Unit> {
    println("My job is ${coroutineContext(Job)}")    
}

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

디버그 모드의 출력은 다음과 같습니다.

My job is "coroutine#1":BlockingCoroutine{Active}@6d311334

CoroutineScope~에서 활성~이다 coroutineContext(Order)?.isActive == true 편리한 사용을 위한 바로가기*2입니다.


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

*하나. CoroutineContext는 맵 형식의 내부 요소를 관리합니다. Map의 키 값에 Job이 입력되면 CoroutineContext에서 Job 컴포넌트가 추출됩니다.

public interface Job : CoroutineContext.Element {
    ...
    public companion object Key : CoroutineContext.Key<Job>
    ...
}

*2. CoroutineScope.isActive 확장 함수는 CoroutineScope의 coroutineContext에서 작업 개체를 가져온 다음 작업이 활성 상태인지 확인하고 null이면 true를 반환합니다.

@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public val CoroutineScope.isActive: Boolean
    get() = coroutineContext(Job)?.isActive ?: true

즉, coroutineScope에는 CoroutineContext가 하나만 존재하며, CoroutineContext 내에서는 CoroutineContext.Key를 상속받은 Key 값과 Key 값에 해당하는 Value 값으로 컴포넌트를 관리한다. 이 구성요소에는 코루틴이 현재 실행 중인지 확인하는 작업이 포함되어 있습니다.


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

원래의: 코루틴 컨텍스트 및 디스패처 – 컨텍스트의 작업

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


코 루틴의 자식

코루틴은 다른 코루틴 내에 중첩될 수 있습니다. CoroutineScope내부에서 실행되는 경우 CoroutineScope.coroutineContext다음을 통해 상속된 새로운 코루틴 일하다부모 코 루틴입니다 일하다Child are kill by 부모 코루틴이 취소되면 자식 코루틴도 재귀적으로 취소됩니다.

그러나 부모-자식 관계는 두 가지 방법으로 명시적으로 재정의할 수 있습니다.

  • 코루틴을 실행할 때 두 개의 서로 다른 범위가 명시적으로 설정된 경우(예: GlobalScope 시작), 상위 영역에서 일하다상속하지 마십시오.*1
  • 새 코루틴의 컨텍스트에 다른 작업이 전달되면(아래 예 참조) 상위 범위 작업을 덮어씁니다.*2

두 경우 모두 실행 중인 코루틴은 실행 중인 범위에 바인딩되지 않고 독립적으로 작동합니다.

// launch a coroutine to process some kind of incoming request
val request = launch {
    // it spawns two other jobs
    launch(Job()) { 
        println("job1: I run in my own Job and execute independently!")
        delay(1000)
        println("job1: I am not affected by cancellation of the request")
    }
    // and the other inherits the parent context
    launch {
        delay(100)
        println("job2: I am a child of the request coroutine")
        delay(1000)
        println("job2: I will not execute this line if my parent request is cancelled")
    }
}
delay(500)
request.cancel() // cancel processing of the request
println("main: Who has survived request cancellation?")
delay(1000) // delay the main thread for a second to see what happens

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

코드를 실행한 결과는 다음과 같습니다.

job1: I run in my own Job and execute independently!
job2: I am a child of the request coroutine
main: Who has survived request cancellation?
job1: I am not affected by cancellation of the request


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

*하나. 아래와 같이 CoroutineScope(Dispatchers.IO)로 CoroutineScope를 재정의한다고 가정합니다.

fun main() = runBlocking<Unit> {
    CoroutineScope(Dispatchers.IO).launch {
        ...
    }
}

CoroutineContext가 CoroutineScope에 의해 재정의되면 CoroutineContext는 부모에서 상속되지 않으므로 작업이 없습니다. 따라서 아래와 같이 컨텍스트의 작업이 null인 경우 컨텍스트에 작업을 추가하여 CoroutineScope를 생성합니다.

@Suppress("FunctionName")
public fun CoroutineScope(context: CoroutineContext): CoroutineScope =
    ContextScope(if (context(Job) != null) context else context + Job())

따라서 그녀는 부모 코루틴과 다른 직업을 가집니다.

*2. CoroutineContext는 구성 요소를 키-값으로 관리합니다. 즉, 핵심 작업에 해당하는 값은 하나뿐입니다. 따라서 CoroutineContext에 새로운 job이 지정되면 key job에 해당하는 Value가 새로운 job이 된다.


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

원래의: 코루틴 컨텍스트 및 디스패처 – 코루틴의 자식

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