Однако я также знаю, что пользователей большую часть времени заботит только подмножество хранящихся данных, поэтому внутренняя инициализация выполняется лениво: при первом доступе к каждому полю данные вычисляются и сохраняются для будущего использования.
В небольшом числе случаев пользователям может оказаться полезным хранить эти структуры данных и делиться ими. их между потоками. В нынешнем виде это явно небезопасно, поскольку логика ленивой инициализации будет полна проблем «проверь, а затем действуй».
Я вижу следующие решения:
- Дублировать классы в реальные неизменяемые альтернативы. Поскольку иерархия довольно большая и сложная, я бы предпочел избежать необходимости поддерживать все это.
- Найдите способ «заморозить» структуру данных, чтобы она впоследствии стала действительно неизменяемой. К счастью, это то же самое, что и нетерпеливая инициализация всего.
Код: Выделить всё
public class DataStructure {
private final Map cache = new LinkedHashMap();
public Datum get(index i) { … }
public int size() { … }
public void eager() {
for (int i = 0; i < size(); i++)
get(i);
}
}
Однако я читаю Java Concurrency in Practice, и там упоминается, что безопасная публикация осуществляется через конечные поля. В этом классе нет окончательных полей.
Является ли этот класс потокобезопасным после вызова методаeater()? Если это не так, то как я могу изменить это так, как есть, не заплатив за счастливый путь, где нетерпеливость() никогда не вызывается и потокобезопасность не требуется?
Подробнее здесь: https://stackoverflow.com/questions/798 ... structures
Мобильная версия