以下代码涉及java.util.ConcurrentModificationException
的问题。有没有办法阻止这种情况或允许这种情况?
public void saveHomes() throws IOException {
BufferedWriter br;
br = new BufferedWriter(new FileWriter(homeFile));
Map<String, Location> homesLoc;
System.out.println(homes2.keySet());
for (String player : homes2.keySet()) {
homesLoc = homes2.get(player);
for (String name : homesLoc.keySet()) {
br.write(player + " " + homesLoc.get(name) + " " + name);
br.newLine();
br.flush();
}
}
br.close();
}
答案 0 :(得分:6)
这里的大部分答案似乎都误解了ConcurrentModificationException
的含义,使它们不完整甚至是错误答案。
首先需要了解的是,ConcurrentModificationException
与多个线程对集合的并发访问无关。即使在单线程应用程序中也可能发生这种情况。因此,使用synchronized Map
实现并不是解决问题的正确方法。
ConcurrentModificationException
主要发生在
ConcurrentModificationException
。因此,即使单个线程访问Map
,您仍可能遇到问题。
从您的代码中,没有明显的逻辑来修改集合(homes2
/ homesLoc
)。这可能是由
Map
是一种实现,即使将get()视为结构修改。访问有序的LinkedHashMap就是一个例子。 (我们无法在您的代码中看到)根据您的需要,有不同的解决方案:
ConcurrentHashMap
,它保证迭代器不会抛出ConcurrentModificationException
。迭代将基于迭代器创建时的顺序LinkedHashMap
引起的,您可以通过迭代yourMap.entries()
简单地更改逻辑中的位,这样您就不需要使用额外的get()
获得价值。答案 1 :(得分:3)
答案 2 :(得分:1)
“Java Collection类是快速失败的,这意味着如果在某个线程使用迭代器遍历它时将更改Collection,则iterator.next()将抛出ConcurrentModificationException。”
您正在更改homesLoc然后遍历它。
答案 3 :(得分:-1)
我认为您不应该使用散列图,因为您只是在迭代它,但在java中,哈希表是同步的,因此应该摆脱并发访问问题。
答案 4 :(得分:-1)
您应该使用java.util.Iterator
来遍历密钥集。这会阻止java.util.ConcurrentModificationException
代码:
public void saveHomes() throws IOException {
BufferedWriter br;
br = new BufferedWriter(new FileWriter(homeFile));
Map<String, Location> homesLoc;
System.out.println(homes2.keySet());
Iterator<String> players = homes2.keySet().iterator();
while (players.hasNext()) {
String player = players.next();
homesLoc = homes2.get(player);
Iterator<String> names = homesLoc.keySet().iterator();
while (names.hasNext()) {
String name = names.next();
br.write(player + " " + homesLoc.get(name) + " " + name);
br.newLine();
br.flush();
}
}
br.close();
}