Находясь под впечатлением от вычислительной карты 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 - пожалуйста, подпишите его, если вы считаете приведенный выше пример полезным.