Java具有ThreadLocal变量,这些变量非常适合运行并行操作而无需踩到其他线程或每循环分配,例如OpenCV使用videoCapture.retrieve(image)
,而“image”可以是线程局部变量。
Kotlin对“coroutine-local”变量有什么感觉吗?如果我想采取他们的反例,但每个协程都有一个计数器,我该怎么做?
for (i in 1..1_000_000)
thread(start = true) {
c.addAndGet(i)
}
答案 0 :(得分:3)
如果您正在寻找ThreadLocal
作为性能优化,为了确保每个线程都拥有自己的某个临时对象的副本,那么您应该继续使用ThreadLocal
来实现此目的。可以有比线程更多的协程,并且为每个协程保留一些临时对象的副本可能弊大于利。
如果您正在寻找ThreadLocal
作为传递方法调用的一些上下文的方法,那么我强烈建议考虑将此上下文显式传递给您的函数或使用一些依赖注入框架来做到这一点。
如果你有一个罕见的情况,你确实需要传递一些上下文,但由于某些技术原因,你不能明确地传递它,也不能使用DI(你可以在线程上使用ThreadLocal
) ,您可以将CoroutineContext
与协同程序一起使用。步骤是:
使用以下模板定义自己的coroutine上下文元素类:
class MyContextElement : AbstractCoroutineContextElement(MyContextElement) {
companion object Key : CoroutineContext.Key<MyContextElement>
// you state/code is here
}
创建元素的实例,并在启动协程时将其传递给coroutine构建器。以下示例使用launch
coroutine构建器,但它适用于所有这些构建器(async
,produce
,actor
等)
launch(MyContextElement()) {
// the code of your coroutine
}
您可以使用+
运算符将您的上下文与其他上下文元素相结合(有关详细信息,请参阅"Combining Contexts" in the guide)
从您的协程代码中,您始终可以从coroutineContext
检索元素。所有标准构建器都将CoroutineScope实例引入其范围,这使其coroutineContext
属性可用。如果您深入了解挂起函数的调用堆栈,那么您可以定义自己的coroutineContext()
辅助函数来检索当前上下文,直到它在未来的某个更新中进入标准库。有关详细信息,请参阅KT-17609。
手持coroutineScope
后,您可以轻松检索元素:
val myElement = coroutineScope[MyContextElement]
答案 1 :(得分:0)
对于如今在这个问题上绊脚石的人来说,语法似乎有所变化:
val string =
"""
{
"name": $name,
"value": $value
}
"""
要成为class MyContextElement : AbstractCoroutineContextElement(MyContextElement), CoroutineContext.Element {
override val key = Key
companion object Key : CoroutineContext.Key<KCallScope>
}
,您现在需要实现CoroutineContext.Key
,这要求您实现CoroutineContext.Element
吸气剂。