Я читал довольно много, но не нашел окончательного ответа.
У меня есть класс, который выглядит так:
public class Foo() {
private static final HashMap<String, HashMap> sharedData;
private final HashMap myRefOfInnerHashMap;
static {
// time-consuming initialization of sharedData
final HashMap<String, String> innerMap = new HashMap<String, String>;
innerMap.put...
innerMap.put...
...a
sharedData.put(someKey, java.util.Collections.unmodifiableMap(innerMap));
}
public Foo(String key) {
this.myRefOfInnerHashMap = sharedData.get(key);
}
public void doSomethingUseful() {
// iterate over copy
for (Map.Entry<String, String> entry : this.myRefOfInnerHashMap.entrySet()) {
...
}
}
}
И мне интересно, является ли потокобезопасным доступ к sharedData из экземпляров Foo (как показано в конструкторе и в doSomethingUseful()). Многие экземпляры Foo будут созданы в многопоточной среде.
Мое намерение состоит в том, что sharedData инициализируется в статическом инициализаторе и не изменяется после этого (только для чтения).
Я читал, что неизменяемые объекты по сути являются потокобезопасными. Но я видел это только в контексте переменных экземпляра. Являются ли неизменные статические переменные потоками безопасными?
Другая найденная мной конструкция была ConcurrentHashMap. Я мог бы сделать sharedData типа ConcurrentHashMap, но HashMaps, который он содержит, также должен быть типа ConcurrentHashMap? В основном..
private static final ConcurrentHashMap<String, HashMap> sharedData;
или
private static final ConcurrentHashMap<String, ConcurrentHashMap> sharedData;
Или это было бы безопаснее (но более дорогостоящим просто клонировать())?
this.myCopyOfData = sharedData.get(key).clone();
ТИА.
(Статический инициализатор был отредактирован, чтобы создать больше контекста.)