kotlin中的“协同本地”变量
Java具有ThreadLocal变量,对于运行并行操作而言,不需要videoCapture.retrieve(image)
其他线程或每循环分配,例如OpenCV使用videoCapture.retrieve(image)
,而“image”可以是threadlocal变量。
Kotlin是否具有“协同本地”变量的意义? 如果我想以他们的反例为例,但是每个协程都有一个计数器,那我该怎么做呢?
for (i in 1..1_000_000) thread(start = true) { c.addAndGet(i) }
如果您正在寻找ThreadLocal
作为性能优化,为了确保每个线程都获得一些临时对象的副本,那么您应该继续使用ThreadLocal
。 比线程可以有更多的协程,并且为每个协程保留一些临时对象的副本可能会造成更多的伤害。
如果你正在寻找ThreadLocal
作为传递方法调用的方法,那么我强烈建议考虑明确地将这个上下文传递给你的函数,或者使用一些依赖注入框架来实现。
如果你确实需要传递一些上下文,但是由于某些技术原因,你不能明确地传递它,也不能使用DI(这就是你将ThreadLocal
与线程一起使用的CoroutineContext
),你可以使用CoroutineContext
和协程。 步骤是:
使用以下模板定义您自己的协同程序上下文元素类:
class MyContextElement : AbstractCoroutineContextElement(MyContextElement) { companion object Key : CoroutineContext.Key<MyContextElement> // you state/code is here }
创建元素的实例,并在启动协程时将其传递给协程生成器。 以下示例使用launch
协程生成器,但它适用于所有这些( async
, produce
, actor
等)
launch(MyContextElement()) { // the code of your coroutine }
您可以使用+
运算符将您的上下文与其他上下文元素相结合 (有关详细信息,请参阅指南中的“合并上下文” )
在你的协程代码中,你总是可以从coroutineContext
获取你的元素。 所有标准构建者都将CoroutineScope实例带入其范围,这使得它的coroutineContext
属性可用。 如果您深入调用堆栈的暂停函数,那么您可以定义自己的coroutineContext()
辅助函数来检索当前上下文,直到它在未来更新之一中进入标准库为止。 详情请参阅KT-17609 。
通过使用coroutineScope
,可以轻松地检索元素:
val myElement = coroutineScope[MyContextElement]