提问人:Boris 提问时间:11/16/2023 更新时间:11/16/2023 访问量:24
线程安全版本 Kotlin 中的 ObservableProperty
Thread safe version ObservableProperty in Kotlin
问:
我的应用程序中有以下类:
class SomeService {
@Volatile
var property: String? = null
fun loadProperty() {
// this code loads property value from external source
}
}
- 应用程序中只有一个实例
SomeService
loadProperty
按给定计划从单个线程执行- 应用程序的其他线程可能会到达
someService.property
@Volatile
确保螺纹安全
现在我需要对值更改的事实进行一些后处理。 为此,Kotlin 提供了以下结构:
var property: String? by Delegates.observable(null) { _, _, newValue ->
println(newValue)
}
但是,这种结构不是线程安全的,而不允许添加。
是否有任何现成的 Kotlin 结构来表示线程安全可观察性?
或者编写我自己的支持线程安全的类版本是唯一的选择?@Volatile
ObservableProperty
答:
2赞
Sweeper
11/16/2023
#1
应用委托属性的转换后,您会注意到类中不再有任何可以添加到的属性。@Volatile
private val property$delegate =
object : ObservableProperty<String?>(null) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = ...
}
var property: String?
get() = property$delegate.getValue(this, this::property)
set(value: String?) = property$delegate.setValue(this, this::property, value)
@Volatile
不能继续下去,因为它从未真正改变过,它不能继续下去,因为它不再有后盾。property$delegate
property
这基本上意味着您需要制作自己的.实际需要的是(来源)中的这个属性:ObservableProperty
@Volatile
value
ObservableProperty
public abstract class ObservableProperty<V>(initialValue: V) : ReadWriteProperty<Any?, V> {
// this needs to be volatile
private var value = initialValue
现在知道了这一点,编写自己的易失性版本很容易:
inline fun <V> Delegates.volatileObservable(initialValue: V, crossinline onChange: (property: KProperty<*>, oldValue: V, newValue: V) -> Unit) =
object: ObservableVolatileProperty<V>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: V, newValue: V) =
onChange(property, oldValue, newValue)
}
abstract class ObservableVolatileProperty<V>(initialValue: V) : ReadWriteProperty<Any?, V> {
@Volatile
private var value = initialValue
protected open fun afterChange(property: KProperty<*>, oldValue: V, newValue: V) {}
override fun getValue(thisRef: Any?, property: KProperty<*>) = value
// @Synchronized is needed if you are setting it from multiple threads
@Synchronized
override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
val oldValue = this.value
this.value = value
afterChange(property, oldValue, value)
}
}
评论
property
loadProperty()
loadProperty()