有时当我需要延迟初始化的字段时,我会使用以下设计模式。
class DictionaryHolder {
private volatile Dictionary dict; // some heavy object
public Dictionary getDictionary() {
Dictionary d = this.dict;
if (d == null) {
d = loadDictionary(); // costy operation
this.dict = d;
}
return d;
}
}
它看起来像 Double Checking idion,但不完全是。没有同步,loadDictionary
方法可能会被多次调用。
我在并发性很低的时候使用这个模式。在使用此模式时,我还要牢记以下假设:
loadDictionary
方法始终返回相同的数据。loadDictionary
方法是线程安全的。
我的问题:
- 这个模式正确吗?换句话说,
getDictionary()
是否可能返回无效数据? - 是否可以使
dict
字段保持非 volatile 以提高效率? - 有没有更好的解决方案?
最佳答案
我个人觉得Initialization on demand holder idiom很适合这种情况。来自维基:
public class Something {
private Something() {}
private static class LazyHolder {
private static final Something INSTANCE = new Something();
}
public static final Something getInstance() {
return LazyHolder.INSTANCE;
}
}
虽然这看起来像是一种纯粹用于单例控制的模式,但您可以用它做很多更酷的事情。例如holder 类可以调用一个方法,该方法反过来填充某种数据。
此外,在您的情况下,如果多个线程在 loadDictionary 调用(同步)上排队,您可能最终会多次加载相同的内容。
关于Java,没有同步的延迟初始化字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5567801/