1

如果我同时修改一个 Java Set,我会得到一个 ConcurrentModificationException。问题是堆栈跟踪表明在某个 Map 迭代器上遇到了修改。我现在明白 Maps 是用来在 java 中实现 Sets 的,但这些细节是实现内部的。我相信内部 Map 迭代器异常应该被正确地包装在应该被传回的 Set Iterator 相关异常中。

我有道理还是我错过了什么?我只花了两天时间试图在代码中找到不存在的错误 Map 操作,但最终偶然发现了导致问题的 Set 操作(通过反复试验,而不是通过逻辑过程或文档放大)。我想知道将来如何避免这种挫败感。

------------更新------------- 我的查询不是关于如何获得正确的并发性。我的问题是如何避免被这种无用的堆栈跟踪消息误导。Map Iterator 异常没有业务显示在堆栈跟踪中,而不是实际的 SetIterator 异常,这从用户的角度来看是有意义的

4

3 回答 3

1

虽然表面上看起来有点奇怪,但当您遇到此类错误时,堆栈跟踪应该为您提供所需的信息 - 忽略跟踪的前几行,它们是内部的,java.util并寻找对您的一个的第一个引用自己的课。此行将是您调试时开始查找的地方。

至于为什么 a 上的迭代器HashSet看起来是 map 相关而不是 set 相关类型,这是因为它-HashSet.iterator简单的实现 return backingMap.keySet().iterator()。没有这样的“SetIterator”。

于 2013-02-25T08:57:10.680 回答
0

您可以使用允许并发修改的 Set。与 ConcurrentSkipListSet 或 CopyOnWriteArraySet 一样,Google Guava 也有其他获取并发集的方法。

于 2013-02-25T08:20:27.420 回答
0

一个 ConcurrentModificationException 发生在一个集合被迭代,并且另一个线程试图修改它时;或相反亦然。我理解您的观点,但解决此问题的一种简单方法是简单地设置一个布尔标志,指示正在迭代该集合。这样,您的修改线程可以简单地等待该标志变为假,并且您的线程将永远不会发生这样的冲突:)

于 2013-02-25T07:54:17.347 回答