Я понимаю, что есть похожие вопросы/ответы на этот вопрос, но я не могу найти именно то, что ищу.
Я хочу реализовать кеш в памяти, который кэширует результат вызова БД, который выполняет проверку существования. Эта проверка существования довольно дорогая, и, как только объект существует в БД, он никогда не будет удален, поэтому все, что мне нужно, это очень простой кеш в памяти (даже в процессе). После выполнения вызова БД процесс запоминает результат проверки существования для этого идентификатора и не должен снова вызывать БД.
(Может быть, еще одна вещь, которую следует упомянуть, это то, что если объект не существует в БД, он будет создан).
Я использую для этого HashSet (java) и просто добавляю идентификатор в набор, когда проверка/создание выполняется, однако это очень параллельная среда, и я не уверен в последствиях отсутствия HashSet-поточности.
Код всегда использует только методы add() и contains() (без итерации).
Я действительно не забочусь о промахе кеша (и получающемся в результате дополнительном вызове БД) здесь и там, но мне интересно, может ли этот шаблон add() и contains() вызываться на наборе в параллельных потоках к более катастрофическим ошибкам.
Для этого вы можете использовать библиотеку ehCache.
Из любопытства, какие ошибки мы можем ожидать увидеть в этом конкретном сценарии? NPE и прочее?
Вы можете использовать ConcurrentHashMap для многопоточного доступа и операции записи. Если вам нужен только HashSet, вы можете использовать ConcurrentHashSet, производный от ConcurrentHashMap. Вы можете использовать вот так.
Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet();
Это правильно для Java 8+. До Java 8: Collections.newSetFromMap(map)
Я беспокоился о производительности, если все операции синхронизированы, но из некоторого чтения кажется, что, по крайней мере, для чтения нет блокировки. Есть ли здесь какие-либо проблемы с производительностью?
ConcurrentHashMap обладает высокой масштабируемостью, и нам не следует беспокоиться о производительности.
Это хорошее решение. CHM работает по сегментам. Таким образом, производительность будет лучше в любое время
Нет. Если вы хотите использовать Map
в многопоточной среде, используйте Collections.synchronizedMap(<map object>)
или ConcurrentHashMap.newKeySet();
:
Set<String> concurrentSet = Collections.synchronizedSet(new HashSet<>());
или...
Set<String> concurrentSet = ConcurrentHashMap.newKeySet();
Нет, это не безопасно. Вы одновременно читаете и пишете в не потокобезопасную коллекцию. Это никогда не бывает безопасно.