逻辑很简单:
Foo foo = cache.get();
if (isUpToDate(foo)) {
return foo;
} else {
foo = getUpdatedFoo(); // slow or expensive
cache.put(foo);
return foo;
}
但是,我想确保
getUpdatedFoo()
getUpdatedFoo()
,则线程B不会
叫它,而不是等待线程A的结果我可能会根据JCiP的Memoizer模式拼凑一些东西,但我怀疑有一种更简单的方法 - 可能使用Guava CacheBuilder?但是,如何不是很明显。
更新:根据以下FrankPL's answer实施双重检查锁定模式:
Foo foo = cache.get();
if (!isUpToDate(foo)) {
lock.lock(); // Will block if some other thread is refreshing
try {
// See if some other thread already refreshed for us
foo = cache.get();
if (!isUpToDate(foo)) {
// guess not, we'll refresh it ourselves
foo = getUpdatedFoo();
cache.put(foo);
}
} finally {
lock.unlock();
}
}
return foo;
答案 0 :(得分:0)
有关您可以使用的双重检查锁定模式,请参阅http://en.wikipedia.org/wiki/Double-checked_locking。请使用您的new Helper()
。
getUpdatedFoo()
答案 1 :(得分:0)
也许您可以考虑使用读写锁(http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html)。下面给出了一个示例代码:
rwlock.readLock().lock();
Foo foo = cache.get();
if(isUpToDate(foo)) {
rwlock.readLock.unlock();
return foo;
} else {
rwlock.readLock.unlock();
rwlock.writeLock.lock();
// recheck if updated
Foo foo = cache.get();
if(isUpToDate(foo)) {
rwlock.writeLock.unlock();
return foo;
} else {
foo = getUpdatedFoo();
cache.put(foo);
rwlock.writeLock.unlock();
return foo;
}
}