2017-07-26 87 views
-2

,如果我发现了以下错误HashMap中抛出ConcurrentModificationException的

Map<String, Object> foodData = new HashMap<String, Object>(); 
    foodData.put("penguin", 1); 
    foodData.put("flamingo", 2); 
    Map<String,Object> synchronizedFoodData = Collections.synchronizedMap(foodData); 
    for(String key: synchronizedFoodData.keySet()) 
    synchronizedFoodData.remove(key); 

问题: - 为什么此代码抛出一个ConcurrentModificationException在运行,而与ConcurrentHashMap相同的代码没有: -

Map<String, Object> foodData = new ConcurrentHashMap<String, Object>(); 
    foodData.put("penguin", 1); 
    foodData.put("flamingo", 2); 
    Map<String,Object> synchronizedFoodData = Collections.synchronizedMap(foodData); 
    for(String key: synchronizedFoodData.keySet()) 
    synchronizedFoodData.remove(key); 

为什么它没有显示任何错误。 林期待的内部工作有一些明显的例子: -

我仍然使用Collections.synchronizedMap(foodData)手段;仍然有错误,应该不是这种情况。

  1. 我的第一个代码有什么问题?
  2. 然后HashMap和Collections.synchronizedMap都抛出错误,所以何时使用synchronizedMap?
+1

从ConcurrentHashMap中的文档:“他们不抛出ConcurrentModificationException” –

+0

也许是因为'ConcurrentHashMap'是'synchronizedMap',看到这个链接HTTPS ://examples.javacodegeeks.com/java-basics/java-map-example/ – AsfK

+0

@EduardoYáñezParareda问题已更改。 –

回答

0

从文档中我们了解到,迭代器返回的是快速失败的,这意味着他们宁愿失败时,他们感觉粗略的东西,而不是继续前进,并最终引入错误。

代码中粗略的部分是如何删除元素。如果地图在之后修改迭代器被创建,它将抛出此异常。您可以通过删除元素通过迭代器自己的删除方法来避免这种情况。

你想要做的是显式创建迭代器并使用该接口来删除项目,而不是遍历Map对象本身。

source

0

因为它们是这样设计的。

检索操作(包括get)通常不会阻塞,因此可能与更新操作(包括put和remove)重叠。检索反映了最近完成的更新操作的结果。对于putAll和clear等集合操作,并发检索可能反映插入或删除仅某些条目。类似地,Iterator和Enumerations在迭代器/枚举创建时或之后返回反映哈希表状态的元素。 他们不会抛出ConcurrentModificationException。但是,迭代器被设计为一次只能由一个线程使用。

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

1

好显示内部工作是不是一件容易的事 - 尤其是在CHM的情况下 - 这是迄今为止不是一个简单的实现。但是,如果你真的想 - 你可以看看来源,并要求具体问题。

所以,你期待一个同步Map来作为CHM从心所欲不抛出异常的去除穿越?情况并非如此,同步与此无关,文件特别没有提及任何事情。所有通过Collections.synchronizedMap保证的是,每个方法都由共享互斥体保护,因此单个线程可以访问单个方法:仅此而已,没有限制。

CHM的内部细节是完全不同的 - 和文档特别说 - Similarly, Iterators, Spliterators 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 java.util.ConcurrentModificationException ConcurrentModificationException

+0

为什么第一个使用HashMap抛出异常的代码? –

+1

@HasnainAliBohra因为这就是实现的工作原理......我不太明白你的问题是诚实的。这就好像为什么'ArrayList'扩展它的内部数组......这只是它被编码的方式。 – Eugene

+1

@HasnainAliBohra你的意思是即使你同步访问它,它仍然抛出一个异常?很好的同步与它为什么不应该在抛出时抛出异常没有任何关系 – Eugene

相关问题