I am working on a REST API as part of some skilling process. My current implementation has a slight concurrency problem when pasting objects into my ConcurrentHashMap.
My code checks if the consumed JSON ID contains. If not, I create a new unique identifier and insert an object. If so, I continue to check if an identifier exists on my card. If the object with the identifier does not exist, I insert the object.
The period between checking whether the HashMap contains a match identifier and inserting an object is a problem when many simultaneous POST requests are executed. A query that has a generated identifier can potentially be written on top of a query in which an identifier was specified if the first query is executed between the lines gcdMap.get(obj.getId()) == nulland the gcdMap.put(obj.getId(), obj);code of the second query. I used Thread.Sleep () to reproduce this problem.
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) {
if (gcdMap.get(obj.getId()) == null) {
Thread.sleep(1000);
gcdMap.put(obj.getId(), obj);
return obj;
} else {
throw new GCDRequestException();
}
} else {
obj.setId(buildId());
gcdMap.put(obj.getId(), obj);
return obj;
}
}
I saw suggestions for using locks, but could not implement them in such a way as to solve this problem. We will be very grateful for any examples, documentation or articles that could help me work out a solution.
Editing: in the comments below I was wrong about three times. I can’t edit them now, but I noticed!