有一个并行计算最常用名称(Human[] people
的函数。但是有数据竞争。为什么呢?
Map<String, Integer> nameMap = new ConcurrentHashMap<>();
Arrays.stream(people)
.parallel()
.filter(p -> p.isAdult())
.map(Human::getName)
.forEach(p -> nameMap.put(p, nameMap.containsKey(p) ? nameMap.get(p) + 1 : 1));
return nameMap.entrySet().parallelStream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();
答案 0 :(得分:3)
因为您正在执行get
,然后增加然后 put
;在某人之间可能已经将该条目放入nameMap
。
您可以在这里使用原子ConcurrentHashMap#merge
,或者更好地使用Collectors.toConcurrentMap
修改强>
你本可以做得更清楚一点:
Arrays.stream(people)
.parallel()
.filter(Human::isAdult)
.collect(Collectors.groupingBy(Human::getName, Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparing(Entry::getValue))
.map(Entry::getKey)
.get();
请注意,我已经接近确定您根本不需要parallel