如果我收到以下错误
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); 仍然会出现错误,这不应该是个案。
答案 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对象本身。
答案 2 :(得分:0)
因为它们是这样设计的。
检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括put和remove)。检索反映了最近完成的更新操作的结果。对于诸如putAll和clear之类的聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。 他们不会抛出ConcurrentModificationException。但是,迭代器设计为一次只能由一个线程使用。
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html