我正在尝试将HashMap <Object, List<Object>>
放入我的dataModel中,但是当我调用template.process()方法时,我得到以下异常:
java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) at freemarker.template.SimpleCollection$SimpleTemplateModelIterator.next(SimpleCollection.java:142) at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:157) at freemarker.core.Environment.visit(Environment.java:351) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:95) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.MixedContent.accept(MixedContent.java:92) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:172) at freemarker.core.Environment.visit(Environment.java:351) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:95) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.MixedContent.accept(MixedContent.java:92) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.Environment.process(Environment.java:176) at freemarker.template.Template.process(Template.java:232)
在查看了一些文章和旧问题之后,我尝试使用ConcurrentHashMap来获得相同的结果。我也尝试使用new HashMap<Object, List<Object>>(oldHashMap)
制作副本。我可以尝试解决这个问题吗?
编辑:我知道ConcurrentModificationExceptions的一般原因。请回复一下,如果你能帮我理解为什么Freemarker框架会抛出这些例外,mkay? =)
谢谢!
答案 0 :(得分:3)
ConcurrentModificationException
是在更改基础集合后使用无效迭代器引起的。解决这个问题的唯一方法就是不要改变你正在迭代的集合。在大多数情况下,这不是由多线程引起的。
简单示例:
//throws an exception in the second iteration
for(String s: list){
list.remove(s);//changes the collection
}
修复1,并非所有迭代器都支持:
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
iter.next();
iter.remove();//iterator still valid
}
修复2:
List<String> toRemove = ...;
for(String s: list){
toRemove.add(s);
}
list.removeAll(toRemove);
答案 1 :(得分:0)
异常意味着,当您在地图上进行迭代时,某些内容已经改变了地图的内容。
你最好的行动方案是找出那些“东西”是什么。例如,它可能是另一个线程,或者可能是您有一个foreach
循环并从循环内修改映射。
很难就如何最好地解决问题提出建议,直到我们明白究竟是什么导致问题以及所期望的行为是什么。
答案 2 :(得分:0)
在执行此类操作时,您会在List
和Map
上遇到此类问题:
List<A> list = ...; //a list with few elements
for(A anObject : list){
list.add(anotherObject); //modify list inside the loop
}
地图也是如此。解决方案是寻找可能在地图上循环内修改地图的地方。或者,如果您使用的是多线程应用程序,那么在您修改它时,另一个线程可能会在地图上循环(反之亦然)。在这种情况下,您需要在两个位置同步对地图的访问:循环代码和地图修改代码。
在TreeMap
here的Java API中有一些信息。
迭代器返回的迭代器 返回的集合的方法 所有这个类的“集合视图 方法“快速失败:如果地图是 随时进行结构修改 在迭代器创建之后,任何一个 除了通过迭代器自己的方式 删除方法,迭代器将抛出 一个ConcurrentModificationException。 因此,面对并发 修改,迭代器失败 快速而干净,而不是 冒着任意,不确定的风险 在一个不确定的时间的行为 未来。
注意一个快速失败的行为 迭代器无法保证 一般来说,是不可能的 做出任何艰难的保证 存在未同步的并发 修改。失败快速的迭代器 抛出ConcurrentModificationException 尽力而为。因此,它 写一个程序是不对的 依赖于这个例外 正确性:失败的快速行为 迭代器应该只用于 检测错误。
答案 3 :(得分:-1)
同步对hashmap的访问,以便一次只能有一个线程访问hashmap。