java - 如果我删除下一个对象,ConcurrentHashMap 将返回 null

标签 java concurrenthashmap

我试图了解故障安全迭代器的工作原理。我在并发 HashMap 中遇到了一些奇怪的事情。代码如下——

    ConcurrentHashMap<String,String> hm = new ConcurrentHashMap<String,String>();
    hm.put("name1", "value1");
    hm.put("name2", "value2");
    hm.put("name3", "value3");

    Iterator<String> itr = hm.keySet().iterator();
    int index = 0;
    while(itr.hasNext()) {
        System.out.println(hm.get(itr.next()));
        hm.put(index+"1", index+"2");
        hm.remove("name2");
        index++;
    }
    System.out.println("--- Second iteration --- ");
    Iterator<String> itr2 = hm.keySet().iterator();
    while(itr2.hasNext()) {
        System.out.println(hm.get(itr2.next()));
    }

打印:

    value3
    null
    value1
    --- Second iteration --- 
    12
    02
    value3
    value1
    22

我很困惑为什么在第一种情况下删除元素被更新,而添加却没有!我使用的是1.8运行环境。

最佳答案

这是因为编辑 Map 时 ConcurrentHashMap 的迭代器不会抛出 ConcurrentModificationException

该映射不会抛出此异常,而是返回反射(reflect)自迭代器创建以来某个时间跨度存在的键/值以及当前时间。 javadoc中也有说明。 :

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset. For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.

如果您需要同时使用值和键,而又不会导致这样的错误,您应该循环遍历 map 的条目集而不是键集,这可以通过以下方式完成:

Iterator<Map.Entry<String,String>> itr = hm.entrySet().iterator();
int index = 0;
while(itr.hasNext()) {
    Map.Entry<String,String> next = itr.next();
    System.out.println(next.getValue());
    hm.put(index+"1", index+"2");
    hm.remove("name2");
    index++;
}

关于java - 如果我删除下一个对象,ConcurrentHashMap 将返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35621663/

相关文章:

java - 以线程安全的方式更新ConcurrentHashMap

java - 通知不显示

java - 如何安全地清理并发映射

java - 比较 JUnit 断言中的数组,简洁的内置方式?

java - 如何在Jedis中使用Redis中的多个键?次要指标

java - Oracle Java ConcurrentHashMap 的错误实现?

Java ConcurrentHashMap 和同步

java - JDK 1.6 和 JDK 1.7 中 ConcurrentHashMap 的不同 `next` 条目

java - 数据类型转换器与 Base64

java - 如何获取有关来电的更多信息