如何使用基于ThreadLocal和Kotlin协程的代码

一些JVM框架使用ThreadLocal来存储应用程序的调用上下文,如SLF4j MDC ,事务管理器,安全管理器等。

但是,Kotlin协同程序是在不同的线程上发送的,所以如何才能工作呢?

(这个问题受GitHub问题的启发)

One Solution collect form web for “如何使用基于ThreadLocal和Kotlin协程的代码”

协程对ThreadLocal的模拟是CoroutineContext

要与ThreadLocal互操作,使用库需要实现支持特定于框架的线程本地的自定义ContinuationInterceptor

这是一个例子。 让我们假设我们使用一些依赖特定ThreadLocal框架来存储一些特定于应用程序的数据(本例中为MyData ):

 val myThreadLocal = ThreadLocal<MyData>() 

为了在协程中使用它,需要实现一个上下文,该上下文保留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) } } } 

要在您的协同程序中使用它,请将您希望与MyContext一起使用的调度程序包装起来,并MyContext提供数据的初始值。 这个值将被放入线程的本地线程中,协程被恢复。

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

上面的实现还会跟踪已完成的线程本地的任何更改并将其存储在此上下文中,所以多次调用可以通过上下文共享“线程本地”数据。

  • Spring 5和Kotlin 1.1协程:类型rx.Scheduler不存在
  • Kotlin协同程序不等待完成
  • 如何实施一个有限的调用与改造阻塞客户端和协程
  • 在Android服务中的Kotlin协程
  • Android中的Kotlin协程:为什么要使用Anko中的bg()而不是async()?
  • Kotlin:ArrayIndexOutOfBoundsException在将DispatchTask转换为字符串期间
  • Kotlin协同程序:包装cassandra同步使用vs翻译异步使用
  • 什么关闭kotlinx.coroutines通道呢
  • Kotlin协同程序:测试Android Presenter时切换上下文
  • 使用单元测试支持清理Kotlin中的协程
  • Kotlin协程和Spring Framework 5反应类型
  • Kotlin language will be the best programming language for Android.