Впечатленный функцией вычислительной карты Guava , я ищу своего рода «вычислительную ссылку» - реализацию эталонной ленивой загрузки, которая параллельна простоте Guava использования, под которым я подразумеваю, что он обрабатывает все блокировки, загрузку и обработку исключений под капотом, предоставляя только метод get ()
.
После того, как краткий поиск ничего не дал, я быстро использовал свой собственный в качестве доказательства концепции:
public abstract class ComputingRef implements Callable {
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;
}
}
This ComputingRef
может быть анонимно расширен для реализации call ()
, который функционирует как фабричный метод:
ComputingRef lazySingletonRef = new ComputingRef() {
@Override
public MyObject call() {
//fetch MyObject from database and return
}
};
Я не удовлетворен тем, что эта реализация оптимальна, но она демонстрирует то, что мне нужно.
Позже я нашел этот пример из T2 Framework , который кажется более сложным.
Теперь у меня следующие вопросы:
РЕДАКТИРОВАТЬ: Обновил мою реализацию, чтобы использовать локальную переменную, как это было предложено @ неотменяемый ответ - пожалуйста, проголосуйте за нее, если найдете выше пример полезный.