受到Guava的计算地图功能的印象,我正在寻找一种类似于"计算参考"的东西——一种懒加载的参考实现,与Guava的易用性相媲美,也就是说它在幕后处理所有锁定、加载和异常处理,仅公开一个get()
方法。
经过简短的搜索没有找到合适的内容,我很快自己编写了一个作为概念验证:
public abstract class ComputingRef<T> implements Callable<T> {
private volatile T referent = null;
private Lock lock = new ReentrantLock();
public T get() {
T temp = referent;
if (temp == null) {
lock.lock();
try {
temp = referent;
if (temp == null) {
try {
referent = temp = call();
}
catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
}
else {
throw new RuntimeException(e);
}
}
}
}
finally {
lock.unlock();
}
}
return temp;
}
}
这个 ComputingRef
可以匿名扩展来实现 call()
,它作为工厂方法起作用:
ComputingRef<MyObject> lazySingletonRef = new ComputingRef<MyObject>() {
@Override
public MyObject call() {
//fetch MyObject from database and return
}
};
我不满意这个实现是否最优,但它演示了我的目的。
后来我发现T2 Framework中的这个例子,它似乎更加复杂。
现在我的问题是:
- 如何改进我上面的代码?
- 与T2示例相比,它如何,并且该示例的更高复杂性提供了什么优势?
- 在我的搜索中是否错过了其他懒加载引用的实现?
编辑:根据@irreputable的答案建议更新了我的实现-如果您发现上面的示例有用,请点赞。
AtomicReference
呢? - Alistair A. IsraelAtomicReference
似乎不能自己支持延迟加载。 - Paul Bellora