使用ConcurrentHashMap时的并发问题
我一直在研究REST API作为一些技能的一部分。 将对象插入到我的ConcurrentHashMap时,我当前的实现有一个小的并发问题。
我的代码检查消费的JSON是否包含ID。 如果不是,我创建一个新的唯一ID并插入该对象。 如果是,我继续检查我的地图中是否存在该ID。 如果没有存在ID的对象,则插入该对象。
检查HashMap是否包含匹配的ID并插入对象之间的时间段在发出多个并发POST请求时证明是一个问题。 如果第一个请求在gcdMap.get(obj.getId()) == null
和gcdMap.put(obj.getId(), obj);
gcdMap.get(obj.getId()) == null
之间执行,那么具有生成的ID的请求可能会被请求写入, 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;
}
}
我已经看到了有关使用锁的建议,但无法以解决此问题的方式实现它们。 任何可能帮助我制定解决方案的示例,文档或文章都将不胜感激。
编辑:我在下面的评论中拼错了三次。 我现在无法编辑它们,但我注意到了!
使用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/91901.html