HashMap抛出ConcurrentModificationException

时间:2017-07-26 06:22:20

标签: java java-8

如果我收到以下错误

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); 的代码相同没有: -

{{1}}

为什么它没有显示任何错误。 我希望内部使用一些明确的例子: -

意味着我仍在使用 Collections.synchronizedMap(foodData); 仍然会出现错误,这不应该是个案。

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

3 个答案:

答案 0 :(得分:1)

很好地展示内部工作并不容易 - 特别是在public class ClipBoards { public static void copyToClipBoard(@NonNull Context context, @NonNull CharSequence text) { ClipData clipData = ClipData.newPlainText("rebase_copy", text); ClipboardManager manager = (ClipboardManager) context .getSystemService(Context.CLIPBOARD_SERVICE); manager.setPrimaryClip(clipData); } } 的情况下 - 它到目前为止并不是一个简单的实现。但如果你真的想 - 你可以查看来源并询问具体的问题。

那么,您希望同步CHM充当Map ,而在遍历时删除时抛出异常?情况并非如此,synchronized与此无关,文档特别没有说明任何内容。通过CHM保证的是,每个方法都受共享互斥锁的保护,因此单个线程可以访问单个方法:仅此而已。

Collections.synchronizedMap的内部细节完全不同 - 文档明确指出 - CHM

答案 1 :(得分:0)

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

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

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

source

答案 2 :(得分:0)

因为它们是这样设计的。

  

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

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