2017-09-14 30 views
6

कुछ जेवीएम फ्रेमवर्क ThreadLocal का उपयोग किसी अनुप्रयोग के कॉल संदर्भ को स्टोर करने के लिए करते हैं, जैसे SLF4j MDC, लेनदेन प्रबंधक, सुरक्षा प्रबंधक और अन्य।कोटलिन कोरआउट के साथ थ्रेडलोकल पर निर्भर कोड का उपयोग कैसे करें

हालांकि, कोटलिन कोरआउट को विभिन्न धागे पर प्रेषित किया जाता है, तो इसे काम करने के लिए कैसे बनाया जा सकता है?

(प्रश्न GitHub issue से प्रेरित है)

उत्तर

8

ThreadLocal को coroutine के अनुरूप CoroutineContext है।

ThreadLocal के साथ इंटरऑपरेट करने के लिए-पुस्तकालयों को आप कस्टम ContinuationInterceptor को कार्यान्वित करने की आवश्यकता है जो फ्रेमवर्क-विशिष्ट थ्रेड-लोकल का समर्थन करता है।

यहां एक उदाहरण है। हमें लगता है कि हम (इस उदाहरण में MyData) कुछ आवेदन विशेष डाटा स्टोर करने के लिए कुछ रूपरेखा है कि एक विशिष्ट ThreadLocal पर निर्भर करता है का उपयोग करते हैं:

val myThreadLocal = ThreadLocal<MyData>() 

coroutines के साथ उपयोग करने के लिए, यदि आप कोई संदर्भ को लागू करने की आवश्यकता होगी कि MyData का वर्तमान मान रखता है और इसे थ्रेड पर फिर से शुरू होने पर हर बार संबंधित 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) } 
    } 
} 

अपने coroutines में इसका इस्तेमाल करने के लिए आपको डिस्पैचर कि आप MyContext साथ उपयोग करें और यह अपने डेटा का प्रारंभिक मूल्य देना चाहता हूँ लपेट दें। यह मान थ्रेड-थ्रेड पर थ्रेड पर रखा जाएगा जहां कोरआउट शुरू हो जाएगा।

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

कार्यान्वयन ऊपर भी धागे की स्थानीय कि किया गया था में कोई परिवर्तन ट्रैक करना चाहते हैं और इस संदर्भ में संग्रहीत है, तो इस तरह से कई मंगलाचरण संदर्भ के माध्यम से "धागे की स्थानीय" डेटा साझा कर सकते हैं।

संबंधित मुद्दे