从 ConcurrentHashMap 中移除

Removing from a ConcurrentHashMap

我正在尝试从 ConcurrentHashMap 中删除某些条目。然而,由于这发生在多线程环境中,条目可能会在迭代过程中被删除 and/or 修改。发生这种情况时,迭代器上的 remove 方法将删除该条目,即使它自从通过 next 收到以来已被修改。我构建了一个示例程序来说明这一点:

ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

map.put("foo", "bar");
map.put("quz", "qaz");

CountDownLatch foundBar = new CountDownLatch(1);
CountDownLatch doneModifying = new CountDownLatch(1);
CountDownLatch doneIterating = new CountDownLatch(1);

new Thread(() -> {
    try {
        Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String> entry = it.next();
            if (entry.getValue().equals("bar")) {
                foundBar.countDown();
                doneModifying.await();
                it.remove();
            }
        }
        doneIterating.countDown();
    } catch (InterruptedException e) {
        throw new Error(e);
    }
}).start();

foundBar.await();
map.put("foo", "nob");
doneModifying.countDown();

doneIterating.await();
System.out.println(map);

输出将是 {quz=qaz} 而不是我预期的 {quz=qaz,foo=nob}。我的问题是:如何实现所需的行为? remove(key, value)迭代过程中Map上的方法是否是正确的选择?

是的,您应该使用两个参数 remove 方法。虽然在迭代期间直接改变集合对于大多数 java 集合来说通常是一件坏事,但 ConcurrentHashMap 允许这样做。