Я работаю над REST API как часть некоторого процесса skilling. Моя текущая реализация имеет небольшую проблему параллелизма при вставке объектов в мою ConcurrentHashMap.Проблема параллелизма при использовании ConcurrentHashMap
Мой код проверяет, содержит ли потребленный JSON ID. Если нет, я создаю новый уникальный идентификатор и вставляю объект. Если да, я продолжаю проверять, существует ли идентификатор на моей карте. Если объект с идентификатором не существует, я вставляю объект.
Период между проверкой того, содержит ли HashMap идентификатор соответствия и вставка объекта, является проблемой при выполнении многих одновременных запросов POST. Запрос, который имеет сгенерированный идентификатор, может быть потенциально написан поверх запроса, в котором идентификатор был указан, если первый запрос выполнен между gcdMap.get(obj.getId()) == null
и gcdMap.put(obj.getId(), obj);
строками кода второго запроса. Я использовал Thread.Sleep() для воспроизведения этой проблемы.
public static ConcurrentMap<Long, GCDObject> gcdMap = new ConcurrentHashMap<Long, GCDObject>();
@POST
@Consumes(MediaType.APPLICATION_JSON)
public GCDObject create(GCDObject obj) throws GCDRequestException {
obj.setTimestamp(LocalDateTime.now());
obj.setResult(GCD.calculate(obj.getX(), obj.getY()));
if (obj.getId() != null) { // JSON contains ID
if (gcdMap.get(obj.getId()) == null) { // If map does not contain obj with ID already,
Thread.sleep(1000);
gcdMap.put(obj.getId(), obj); // Put obj into map.
return obj;
} else { // else map already contains ID,
throw new GCDRequestException();
}
} else { // JSON contains no ID
obj.setId(buildId()); // Build ID
gcdMap.put(obj.getId(), obj); // Put into map
return obj;
}
}
Я видел предложения для использования замков, но не смогли реализовать их таким образом, который решает эту проблему. Будем очень благодарны за любые примеры, документацию или статьи, которые могли бы помочь мне выработать решение.
Редактировать: Я неправильно опечатал около трех раз в комментариях ниже. Я не могу сейчас их редактировать, но я заметил!
Вы используете Java 8? – shmosel
Да Я использую Java 8. – Afterfield
вы пробовали использовать другие методы ConcurrentHashMap, такие как putIfAbsent & getOrDefault, а также параллельный запрос POST, отличный или похожий? –