Kotlin委托属性为线程本地的懒惰
问题描述:
是否有一种简单的方式获得委托属性by lazy
的每个线程计算的值如ThreadLocal
?Kotlin委托属性为线程本地的懒惰
LazyThreadSafetyMode
控制并发初始化,与.NONE
通过允许多个线程来接近所期望的功能,以接收不同的值,但具有随后的后初始化调用引用相同的对象时,线程不管返回相同的奇异值,与某些情况下返回null
。
无论并发初始化或后期初始化,该属性都会缓存每个线程的唯一值。
答
Kotlin delegates很容易通过您自己的实现进行扩展。
-
你可以让你的委托保持与
initialValue
一个ThreadLocal<T>
通过传递函数计算:class ThreadLocalLazy<T>(val provider:() -> T) :ReadOnlyProperty<Any?, T> { private val threadLocal = object : ThreadLocal<T>() { override fun initialValue(): T = provider() } override fun getValue(thisRef: Any?, property: KProperty<*>): T = threadLocal.get() }
-
或维持
Lazy<T>
每个线程有ThreadLocal<Lazy<T>>
,让您的代理可以实现Lazy<T>
本身:class ThreadLocalLazy<T>(val provider:() -> T) : Lazy<T> { private val threadLocal = object : ThreadLocal<Lazy<T>>() { override fun initialValue(): Lazy<T> = lazy(LazyThreadSafetyMode.NONE, provider) } override val value get() = threadLocal.get().value override fun isInitialized() = threadLocal.get().isInitialized() }
这里有一个方便的功能来创建委托的实例:
fun <T> threadLocalLazy(provider:() -> T) = ThreadLocalLazy(provider)
然后,只需委派属性threadLocalLazy { ... }
。使用示例:
class Example {
val threadId by threadLocalLazy { Thread.currentThread().id }
}
fun main(args: Array<String>) {
val example = Example()
repeat(3) {
thread {
println(example.threadId) // should print three different numbers
}
}
}