Coroutine Context와

코루틴 범위

컨텍스트, 어린이 및 작업에 대한 지식을 결합해 봅시다.

애플리케이션에 코루틴과 수명 주기가 다른 개체가 있다고 가정합니다.

예를 들어 다양한 코루틴을 실행하여 Android 애플리케이션 빌드, Android 활동 컨텍스트에서 데이터 가져오기 및 업데이트 또는 애니메이션 실행과 같은 비동기 작업을 수행할 수 있습니다.

이러한 코루틴은 활동이 소멸될 때 메모리 누수를 방지하기 위해 중단되어야 합니다.

물론 Context와 Jobs를 직접 조작하여 Activity의 코루틴 수명 주기를 결합할 수 있습니다.

하지만, kotlinx.코루틴 패키지는 CoroutineScope를 캡슐화하는 추상화를 제공합니다.

활동의 수명 주기에 바인딩된 CoroutineScope 인스턴스를 생성하여 코루틴의 수명 주기를 관리합니다.

CoroutineScope 인스턴스는 CoroutineScope() 또는 MainScope()와 같은 팩터리 함수를 사용하여 만들 수 있습니다.

전자는 범용 범위를 만들고 후자는 UI 응용 프로그램에 대한 범위를 만들고 Dispatchers.Main을 기본 디스패처로 사용합니다.

class Activity {
    private val mainScope = MainScope()

    fun destroy() {
        mainScope.cancel()
    }
    // to be continued ...

이제 정의된 범위를 사용하여 활동 범위 내에서 코루틴을 실행할 수 있습니다.

시연을 위해 시간 지연이 다른 10개의 코루틴을 만들어 보겠습니다.

// class Activity continues
    fun doSomething() {
        // launch ten coroutines for a demo, each working for a different time
        repeat(10) { i ->
            mainScope.launch {
                delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
                println("Coroutine $i is done")
            }
        }
    }
} // class Activity ends

활동은 기본 기능과 테스트 기능에서 생성됩니다.

뭔가를 500ms 후에 활동을 파괴합니다.

그건 뭔가를에서 실행 중인 모든 코루틴을 취소합니다.

활동이 소멸된 후 조금 더 기다려도 아무런 메시지가 표시되지 않는 것을 확인할 수 있습니다.

val activity = Activity()
activity.doSomething() // run test function
println("Launched coroutines")
delay(500L) // delay for half a second
println("Destroying activity!
") activity.destroy() // cancels all coroutines delay(1000) // visually confirm that they don't work

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

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

Launched coroutines
Coroutine 0 is done
Coroutine 1 is done
Destroying activity!

Activity.destory()에서 job.cancel()을 한 번 호출하면 처음 두 개의 코루틴만 메시지를 인쇄하고 나머지는 취소되는 것을 볼 수 있습니다.

Android는 수명 주기가 있는 모든 엔터티*1에서 CoroutineScope를 지원합니다.

다음 문서보자

스레드 로컬 데이터

코루틴 또는 코루틴 간에 스레드 로컬 데이터를 전달하는 함수가 있으면 편리합니다.

그러나 코루틴은 특정 스레드에 연결되어 있지 않으므로 상용구를 직접 만들 수 있습니다.

이것을 해결하기 위해 스레드로컬누군가를 위해 asContextElement로 확장 기능이 있습니다.

이렇게 하면 지정된 ThreadLocal의 값을 유지하고 코루틴이 컨텍스트를 변경할 때 복원하는 추가 컨텍스트 구성 요소가 생성됩니다.

이것은 직접 살펴보면 쉽게 설명됩니다.

threadLocal.set("main")
println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
    println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
    yield()
    println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
}
job.join()
println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")

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

이 예에서 우리는 디스패처 기본값백그라운드 스레드 풀에서 새 코루틴을 시작합니다.

따라서 스레드 풀이 아닌 다른 스레드에서 실행되지만 어느 스레드에서 실행되든 상관없이 threadLocal.asContextElement(value = “launch”)로 지정된 스레드 로컬 변수의 값을 가집니다.

따라서 결과 값은 다음과 같습니다.

Pre-main, current thread: Thread(main @coroutine#1,5,main), thread local value: 'main'
Launch start, current thread: Thread(DefaultDispatcher-worker-1 @coroutine#2,5,main), thread local value: 'launch'
After yield, current thread: Thread(DefaultDispatcher-worker-2 @coroutine#2,5,main), thread local value: 'launch'
Post-main, current thread: Thread(main @coroutine#1,5,main), thread local value: 'main'

적절한 컨텍스트 요소를 설정하는 것을 잊기 쉽습니다.

코루틴을 실행하는 스레드가 다른 경우 스레드가 액세스하는 스레드 로컬 변수는 예측할 수 없는 값을 가질 수 있습니다.

이런 상황을 피하기 위해 선물하다 남용 시 방법 및 Fail-Fast*2 이렇게 하는 것이 좋습니다

스레드로컬최고의 지원을 제공합니다 kotlinx.코루틴 패키지의 모든 프리미티브와 함께 사용할 수 있습니다.

그러나 여기에는 한 가지 중요한 주의 사항이 있습니다.

스레드 로컬이 변경되면 새 값이 코루틴 호출자에게 전달되지 않습니다(컨텍스트 요소는 스레드로컬 (개체에 대한 액세스를 추적할 수 없기 때문에) 변경된 값은 다음 일시 중단 시 손실됩니다.

스레드 로컬을 코루틴으로 변경 맥락과 함께자세한 내용을 사용하자 asContextElement로보다

또는 스레드 로컬 변수 클래스 카운터(var i: int) 와 같은 상자 변경 *3 그러나 이 경우 변경 가능한 상자의 변수 값을 동기화하는 전체 책임이 동시에 액세스되고 변경됩니다.

로깅 MDC, 트랜잭션 컨텍스트 또는 데이터를 넘겨주기 위해 내부적으로 스레드 로컬을 사용하는 다른 라이브러리와 마찬가지로 스레드 로컬의 고급 사용은 구현해야 하는 인터페이스를 설명합니다.

ThreadContext 요소 설명서를 참조하십시오.


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

*하나. 활동 및 ViewModel을 의미합니다.

Activity는 lifecycleScope를 제공하고 ViewModel은 viewModelScope를 제공합니다.

*2. 그것은 빨리 실패한다는 것을 의미합니다.

*삼. 변경 가능한 상자는 변수가 클래스에 포함된 클래스입니다.


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

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

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


목차로 돌아가기

코루틴 가이드

언어로서 Kotlin은 다른 라이브러리가 코루틴을 사용할 수 있도록 표준 라이브러리에 최소한의 저수준 API를 제공합니다.

유사한 기능을 가진 다른 많은 언어와 달리 async 및 await는 K입니다.

translatedev.com