我想在删除条目时定期迭代 ConcurrentHashMap
,如下所示:
for (Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Entry<Integer, Integer> entry = iter.next();
// do something
iter.remove();
}
问题是在我迭代时另一个线程可能正在更新或修改值。如果发生这种情况,这些更新可能会永远丢失,因为我的线程在迭代时只会看到陈旧的值,但 remove()
将删除 Activity 条目。
经过一番考虑,我想到了这个解决方法:
map.forEach((key, value) -> {
// delete if value is up to date, otherwise leave for next round
if (map.remove(key, value)) {
// do something
}
});
这样做的一个问题是,它不会捕获对未实现 equals()
(例如 AtomicInteger
)的可变值的修改。有没有更好的方法来安全删除并发修改?
最佳答案
您的解决方法可行,但存在一种可能的情况。如果某些条目不断更新,则 map.remove(key,value) 在更新结束之前可能永远不会返回 true。
如果你使用JDK8,这里是我的解决方案
for (Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Entry<Integer, Integer> entry = iter.next();
Map.compute(entry.getKey(), (k, v) -> f(v));
//do something for prevValue
}
....
private Integer prevValue;
private Integer f(Integer v){
prevValue = v;
return null;
}
compute() 会将 f(v) 应用于值,在我们的例子中,将值分配给全局变量并删除条目。
根据 Javadoc,它是原子的。
Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping). The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this Map.
关于java - 在删除条目时迭代 ConcurrentHashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37127285/