【发布时间】:2011-09-23 04:57:31
【问题描述】:
对 Guava 的 computing map feature 印象深刻,我正在寻找一种“计算参考”——一种延迟加载参考实现,它与 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
}
};
我不满意这个实现是最佳的,但它证明了我所追求的。
后来找到this example from the T2 Framework,貌似比较复杂。
现在我的问题是:
- 如何改进我上面的代码?
- 它与 T2 示例相比如何,该示例的复杂性更高提供了哪些优势?
- 我在搜索中遗漏了延迟加载引用的其他实现吗?
编辑:按照@irreputable's answer 的建议更新了我的实现以使用局部变量 - 如果您觉得上述示例有用,请点赞。
【问题讨论】:
-
如果您使用的是 Java 5 及更高版本,为什么不直接使用
AtomicReference? -
@AlistairIsrael - 我可能弄错了,但
AtomicReference本身似乎不支持延迟加载。 -
@AlistairIsrael - 或者你的意思是我应该在我的代码示例中使用它而不是
volatile? -
是的,让您的
ComputingMap使用内部AtomicReference,而不是使用锁定并自己实施双重检查锁定。
标签: java reference lazy-loading guava