2017-09-14 1 views

답변

8

ThreadLocal에 코 루틴의 아날로그 CoroutineContext입니다.

라이브러리를 사용하여 ThreadLocal과 상호 운용하려면 프레임 워크 관련 스레드 로컬을 지원하는 사용자 정의 ContinuationInterceptor을 구현해야합니다.

다음은 예입니다. 우리가 (이 예에서는 MyData)를 일부 응용 프로그램 별 데이터를 저장하는 특정 ThreadLocal에 의존하는 일부 프레임 워크를 사용한다고 가정하자 :

val myThreadLocal = ThreadLocal<MyData>() 

는 코 루틴과 함께 사용하려면 컨텍스트를 구현해야하는 현재 값인 MyData을 유지하고 해당 coroutine이 스레드에서 재개 될 때마다 해당 ThreadLocal에 넣습니다. 코드는 다음과 같아야합니다

class MyContext(
    private var myData: MyData, 
    private val dispatcher: ContinuationInterceptor 
) : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor { 
    override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = 
     dispatcher.interceptContinuation(Wrapper(continuation)) 

    inner class Wrapper<T>(private val continuation: Continuation<T>): Continuation<T> { 
     private inline fun wrap(block:() -> Unit) { 
      try { 
       myThreadLocal.set(myData) 
       block() 
      } finally { 
       myData = myThreadLocal.get() 
      } 
     } 

     override val context: CoroutineContext get() = continuation.context 
     override fun resume(value: T) = wrap { continuation.resume(value) } 
     override fun resumeWithException(exception: Throwable) = wrap { continuation.resumeWithException(exception) } 
    } 
} 

당신이 MyContext로 사용하고 그것을 데이터의 초기 값을 부여 할 디스패처 포장, 당신의 코 루틴에서 사용하십시오. 이 값은 coroutine이 다시 시작되는 스레드의 thread-local에 저장됩니다.

launch(MyContext(MyData(), CommonPool)) { 
    // do something... 
} 

위의 구현은 또한 스레드 로컬 이루어졌다에 대한 변경 사항을 추적 할 것이며, 이러한 맥락에 저장되므로이 방법은 여러 호출 컨텍스트를 통해 "스레드 로컬"데이터를 공유 할 수 있습니다.

관련 문제