2017-08-30 39 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 
     } 
    } 
}