Нет, это не потокобезопасно.
Из Javado c из HashMap
:
Обратите внимание, что это реализация не синхронизирована. Если несколько потоков одновременно обращаются к карте ha sh, и хотя бы один из потоков структурно изменяет карту, она должна быть синхронизирована извне.
Итак, синхронизируйте доступ к карте:
String res;
synchronized (features) {
if(!features.containsKey(id)) {
features.put(id, id);
}
res = features.get(id);
}
и сделайте поле final
, а также синхронизируйте внутри инициализатора stati c.
Или, лучше, используйте ConcurrentHashMap
и метод computeIfAbsent
.
String res = concurrentFeatures.computeIfAbsent(id, k -> id);
(HashMap
также имеет метод computeIfAbsent
в Java 8+, но вам нужно вызвать его в синхронизированном тоже блок).
На самом деле, еще лучший способ сделать это в Java 8+ - использовать getOrDefault
, при условии, что вам на самом деле не нужно сохранять ранее невидимый ключ / пары значений:
res = features.getOrDefault(id, id);
Это не изменяет карту, поэтому вам не нужно беспокоиться о безопасности потока; вам просто нужно убедиться, что он инициализирован безопасно:
public final static Map<String, String> features;
static {
Map<String, String> f = new HashMap<>();
f.put("color", "red");
f.put("foo", "bar");
features = f;
}