【发布时间】:2016-05-10 00:04:19
【问题描述】:
我想在删除条目时定期迭代 ConcurrentHashMap,如下所示:
for (Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Entry<Integer, Integer> entry = iter.next();
// do something
iter.remove();
}
问题是在我迭代时另一个线程可能正在更新或修改值。如果发生这种情况,这些更新可能会永远丢失,因为我的线程在迭代时只会看到陈旧的值,但 remove() 将删除实时条目。
经过一番考虑,我想出了这个解决方法:
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)的可变值的修改。有没有更好的方法来安全地删除并发修改?
【问题讨论】:
-
为什么不在做任何工作之前删除条目。
-
@ClaudioCorsi 这不会改变我看到已删除条目的陈旧版本的事实。
-
问题是您需要能够知道自从您开始遍历地图以来更新了哪些内容。即使您可以知道哪些对象已被更新。另一个线程仍然有可能引用了一个已处理但该对象尚未更新的对象。该对象将被添加回来还是只是被更新?这个对象是否应该产生另一个回调?
-
条目是短命的还是长命的?如果它们是短暂的,那么您可以考虑使用弱引用作为值,然后只处理引用队列。
-
@ClaudioCorsi 我说的是地图可见的更新,例如
put()、merge()、compute()等
标签: java multithreading concurrenthashmap