Как использовать код, который опирается на ThreadLocal с сопрограммами Kotlin

Некоторые структуры JVM используют ThreadLocal для хранения контекста вызова приложения, например, SLF4j MDC , менеджеров транзакций, менеджеров безопасности и других.

Тем не менее, Kotlin coroutines отправляются на разные темы, так как это можно сделать для работы?

(Вопрос вызван проблемой GitHub )

Аналогом ThreadLocal для ThreadLocal является CoroutineContext .

Чтобы взаимодействовать с библиотеками ThreadLocal -using, вам необходимо реализовать пользовательский 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... } 

Вышеупомянутая реализация также отслеживала бы любые изменения в локально-потоковом потоке, которые были сделаны, и сохранил их в этом контексте, поэтому таким образом, множественный вызов может совместно использовать «поточно-локальные» данные через контекст.

Intereting Posts
Как я могу вызвать методы Kotlin с помощью reified generics из Java? Как использовать выражение Lamba, чтобы сделать вызовы метода Java менее подробными в Kotlin? Как получить ALBUM ART песни с ее пути в котлин? Весенняя загрузка с одностраничным приложением на AWS Elastic Beanstalk требует дополнительной перенаправления Использование предложения Kotlin WHEN для <, <=,> =,> сравнений Как MutableMap <String, Any?> Передает значение var, когда я использую делегат в Kotlin? Использование цветов, определенных в базовом модуле из функционального модуля, не выполняется после восстановления Android Instant App Как акцептор может добавить значение в состояние и отправить обратно инициатору Почему мы не можем отметить видимость класса как «защищенного» в котлин? Пройдет ли lambdas к Observable.subscribe в kotlin приведет к утечкам памяти? «Недостаточно информации для вывода параметра T» с помощью Kotlin и Android Android Studio 3.0 "JUnit версии 3.8 или более поздней версии" GridView.LayoutParams не существует в Котлине? Kotlin `shl` не работает Как отключить кнопку точки в android Kotlin