private final ConcurrentHashMap<Float, VoteItem> datum = new ConcurrentHashMap<>();
public void vote(float graduation) {
datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(0)));
datum.get(graduation).getNum().incrementAndGet();
}
方法投票是否完全是线程安全的? VoteItem.getNum()返回一个AtomicInteger?或者,如果有更好的方法来实现它?
答案 0 :(得分:4)
如果VoteItem#getNum()
是线程安全的,e。 G。返回最终属性,和在并行线程中不执行任何删除,您的代码也是线程安全的,因为putIfAbsent()
没有机会覆盖现有条目,因此{{}}没有机会1}}返回被覆盖的条目。
但是有更常见的方法可以使用get()
的结果来实现它,如果给定键存在,则会返回现有值:
putIfAbsent()
这也可以处理并发删除的可能性。与您的代码相反,可以在public void vote(float graduation) {
VoteItem i = datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(1)));
if (i != null)
i.getNum().incrementAndGet();
}
和putIfAbsent()
之间执行并发删除,从而导致NPE,这里不会出现这种情况。
并考虑使用computeIfAbsent()
代替get()
以避免无理由putIfAbsent()
创作:
VoteItem
可以在结果上调用public void vote(float graduation) {
datum.computeIfAbsent(graduation, g -> new VoteItem(g, new AtomicInteger(0)))
.getNum()
.incrementAndGet();
}
,因为与getNum()
相反,如果在插入之前值不存在则返回null,它只返回计算值。