Я довольно много читал, но не нашел окончательного ответа.
У меня есть класс, который выглядит так:
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;
or
private static final ConcurrentHashMap<String, ConcurrentHashMap> sharedData;
Или было бы безопаснее (но дороже просто clone ())?
this.myCopyOfData = sharedData.get(key).clone();
TIA.
(Статический инициализатор был отредактирован, чтобы дать больше контекста.)