Логика очень проста:поточно-обновление кэшированных ресурса
Foo foo = cache.get();
if (isUpToDate(foo)) {
return foo;
} else {
foo = getUpdatedFoo(); // slow or expensive
cache.put(foo);
return foo;
}
Однако, я хочу, чтобы убедиться, что
- только один поток вызывает
getUpdatedFoo()
в то время - если нить A уже звонит
getUpdatedFoo()
, нить B не назовите его, вместо этого просто ждите нити A's results
Возможно, я смогу собрать что-то, основанное на шаблоне Memoizer от JCiP, но я подозреваю, что есть более простой способ - возможно, с помощью Guava CacheBuilder? Не сразу очевидно, как, однако.
Update: Реализована блокировка с двойной проверкой шаблон на 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;
Вы можете указать один поток, чтобы обновить кеш в фоновом режиме. – Gray
Вы считаете [ehcache] (http://ehcache.org/) - это действительно так просто, как кажется. – OldCurmudgeon
@ Gray Я мог бы, но до тех пор, пока потоки клиентов будут блокировать ожидание этого потока, я бы предпочел, чтобы один из них выполнял эту работу. –