我遇到了在Scala中以线程安全方式初始化singleton元素的问题。通常使用伴侣对象。但是这次我需要将配置对象传递给初始化器。调用伴随对象的某些init函数要么不是线程安全的,要么导致锁定,这看起来对Scala来说是低级别的(可能我不对)。
我想出的是缓存。使用相同的参数调用缓存有助于将其初始化一次。但对我来说奇怪的是我必须使用具有我需要的更广泛功能的结构。看起来知道缓存只存储一个元素可能会带来更好的性能(至少我们不需要每次都计算参数的哈希值)。 那么Scala中是否有这样的单例只支持一次初始化并忽略进一步调用的参数?
[thread 1]
a = A(config) // initialization is initiated
[thread 2, 3, ..]
a = A(config) // initialized object is used
// only one entity of class should exist
class A(config: Config) {
// should be done once
client = config.getString("client")
}
或者可能是解决问题的其他方法?
答案 0 :(得分:0)
好吧,从概念上讲,几个线程使用相同的(我希望)配置调用初始化似乎很奇怪。在产生线程之前初始化你的单例会更优雅。
如果出于任何原因无法实现,则必须同步初始化。这不是“Scala的级别太低”,需要对并发访问变量进行操作。
您可以使用def apply(config: <some type>)
方法创建一个伴随对象来处理此问题并存储单个私有val。单独的def apply()
可以访问初始化变量,或者如果尚未设置则抛出异常。最后一个不需要同步,因为您只会读取该值。但是,无论出于何种原因,你的课程都是可变的。