2017-08-30 64 views
3

是否有一种简单的方式获得委托属性by lazy的每个线程计算的值如ThreadLocalKotlin委托属性为线程本地的懒惰

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

无论并发初始化或后期初始化,该属性都会缓存每个线程的唯一值。

回答

5

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 
     } 
    } 
}