【问题标题】:Kotlin delegate property by lazy that is thread local惰性的 Kotlin 委托属性是线程本地的
【发布时间】:2017-08-30 22:39:57
【问题描述】:
有没有一种简单的方法来获取委托属性by lazy 的每个线程计算的值,例如ThreadLocal?
LazyThreadSafetyMode 控制并发初始化,.NONE 通过允许多个线程接收不同的值来接近所需的功能,但后续初始化调用引用相同的对象,无论线程如何都返回相同的奇异值,某些情况下返回null。
无论是并发初始化还是后期初始化,该属性都会为每个线程缓存一个唯一值。
【问题讨论】:
标签:
properties
delegates
kotlin
lazy-evaluation
thread-local
【解决方案1】:
Kotlin delegates 很容易通过您自己的实现进行扩展。
-
您可以让您的委托维护一个 ThreadLocal<T> 和 initialValue 由传递的函数计算:
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()
}
-
或者用ThreadLocal<Lazy<T>>为每个线程维护一个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
}
}
}