Kotlin委托属性由lazy本地线程

ers*_*tan 3 delegates properties lazy-evaluation thread-local kotlin

是否有一种简单的方法可以获得by lazy每个线程计算的委托属性值ThreadLocal

LazyThreadSafetyMode控制并发初始化,.NONE通过允许多个线程接收不同的值来接近所需的功能,但后续的后初始化调用引用相同的对象,返回相同的奇异值而不管线程,在某些情况下返回null.

无论是并发初始化还是后期初始化,该属性都会为每个线程缓存一个唯一值.

hot*_*key 6

科特林代表很容易与自己的实现扩展.

  • 你可以让你的委托保持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()
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 或维护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()
    }
    
    Run Code Online (Sandbox Code Playgroud)

这是创建委托实例的便捷功能:

fun <T> threadLocalLazy(provider: () -> T) = ThreadLocalLazy(provider)
Run Code Online (Sandbox Code Playgroud)

然后只需委托一个属性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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)