"coroutine local" kotlin 中的变量
"coroutine local" variables in kotlin
Java 具有适合 运行 并行操作的 ThreadLocal 变量,无需踩踏其他线程或每个循环分配,例如 OpenCV 使用 videoCapture.retrieve(image)
,和 "image" 可以是线程局部变量。
Kotlin 对 "coroutine-local" 变量有任何意义吗?如果我想以他们的反例为例,但每个协程都有一个计数器,我该怎么做?
for (i in 1..1_000_000)
thread(start = true) {
c.addAndGet(i)
}
如果您正在寻找 ThreadLocal
作为性能优化,以确保每个线程都有自己的某个临时对象副本,那么您应该继续使用 ThreadLocal
来达到这个目的。协程可能比线程多得多,为每个协程保留一些临时对象的副本可能弊大于利。
如果您正在寻找 ThreadLocal
作为一种在方法调用周围传递一些上下文的方法,那么我强烈建议考虑将此上下文显式传递到您的函数中或使用一些依赖注入框架来执行此操作。
如果您在极少数情况下确实需要传递一些上下文,但由于某些技术原因您不能显式传递它,也不能使用 DI(即您会使用 ThreadLocal
和线程),您可以将 CoroutineContext
与协程一起使用。步骤是:
使用以下模板定义您自己的协程上下文元素class:
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
}
您可以使用 +
运算符将您的上下文与其他上下文元素结合起来(有关详细信息,请参阅 "Combining Contexts" in the guide)
在您的协程代码中,您始终可以从 coroutineContext
中检索您的元素。所有标准建筑商都带来CoroutineScope instance into their scope, which makes its coroutineContext
property available. If you are deep in the call stack of suspending functions, then you can define your own coroutineContext()
helper function to retrieve the current context until it makes its way into the standard library in one of the future updates. See KT-17609以获取详细信息。
手头有coroutineScope
,检索你的元素很容易:
val myElement = coroutineScope[MyContextElement]
对于现在遇到这个问题的人来说,语法似乎发生了一些变化:
class MyContextElement : AbstractCoroutineContextElement(MyContextElement), CoroutineContext.Element {
override val key = Key
companion object Key : CoroutineContext.Key<KCallScope>
}
为了成为 CoroutineContext.Key
,您现在需要实施 CoroutineContext.Element
,这需要您实施 key
getter.
Java 具有适合 运行 并行操作的 ThreadLocal 变量,无需踩踏其他线程或每个循环分配,例如 OpenCV 使用 videoCapture.retrieve(image)
,和 "image" 可以是线程局部变量。
Kotlin 对 "coroutine-local" 变量有任何意义吗?如果我想以他们的反例为例,但每个协程都有一个计数器,我该怎么做?
for (i in 1..1_000_000)
thread(start = true) {
c.addAndGet(i)
}
如果您正在寻找 ThreadLocal
作为性能优化,以确保每个线程都有自己的某个临时对象副本,那么您应该继续使用 ThreadLocal
来达到这个目的。协程可能比线程多得多,为每个协程保留一些临时对象的副本可能弊大于利。
如果您正在寻找 ThreadLocal
作为一种在方法调用周围传递一些上下文的方法,那么我强烈建议考虑将此上下文显式传递到您的函数中或使用一些依赖注入框架来执行此操作。
如果您在极少数情况下确实需要传递一些上下文,但由于某些技术原因您不能显式传递它,也不能使用 DI(即您会使用 ThreadLocal
和线程),您可以将 CoroutineContext
与协程一起使用。步骤是:
使用以下模板定义您自己的协程上下文元素class:
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
}
您可以使用 +
运算符将您的上下文与其他上下文元素结合起来(有关详细信息,请参阅 "Combining Contexts" in the guide)
在您的协程代码中,您始终可以从 coroutineContext
中检索您的元素。所有标准建筑商都带来CoroutineScope instance into their scope, which makes its coroutineContext
property available. If you are deep in the call stack of suspending functions, then you can define your own coroutineContext()
helper function to retrieve the current context until it makes its way into the standard library in one of the future updates. See KT-17609以获取详细信息。
手头有coroutineScope
,检索你的元素很容易:
val myElement = coroutineScope[MyContextElement]
对于现在遇到这个问题的人来说,语法似乎发生了一些变化:
class MyContextElement : AbstractCoroutineContextElement(MyContextElement), CoroutineContext.Element {
override val key = Key
companion object Key : CoroutineContext.Key<KCallScope>
}
为了成为 CoroutineContext.Key
,您现在需要实施 CoroutineContext.Element
,这需要您实施 key
getter.