Concurrency issue when using ConcurrentHashMap
I've been working on a REST API as part of some up skilling. My current implementation has a small concurrency issue when inserting objects into my ConcurrentHashMap.
My code checks to see whether the consumed JSON contains an ID. If no, I create a new unique ID and insert the object. If yes I continue on to check if the ID already exists in my map. If no object with the ID exists then I insert the object.
The period between checking if the HashMap contains a matching ID and inserting the object is proving to be a problem when many concurrent POST requests are being made. A request that has a generated ID can be potentially written over by a request where the ID has been specified if the first request is executed between gcdMap.get(obj.getId()) == null
and gcdMap.put(obj.getId(), obj);
lines of code of the second request. I have been using 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) { // 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;
}
}
I have seen suggestions for the use of locks but have not been able to implement them in a way that solves this issue. Any examples, documentation or articles that might help me work out a solution would be greatly appreciated.
Edit: I've misspelled absent about three times in the comments below. I can't edit them now but I noticed!
使用putIfAbsent()
有条件地插入:
if (gcdMap.putIfAbsent(obj.getId(), obj) == null) { // If map did not contain obj with ID already,
return obj;
} else { // else map already contained ID,
throw new GCDRequestException();
}
链接地址: http://www.djcxy.com/p/91902.html
上一篇: 如何将Java 8流转换为数组?