编辑:嗯,我觉得很腼腆.我在看错了构造函数.根据Kal的回答,被调用的真实构造函数(见下文) - 违反了foreach循环的并发规则.
无论如何,谢谢你的帮助!它仍然可以帮助我修复代码中的实际错误.
所有
我是一个非常新的Java程序员,我只是刚开始掌握语言的基本句柄.我目前正在与对话参与者系统的工作,但已先行试图让逻辑的条款我们的系统的陈述符合规格.我差不多完成了,但遇到了以下错误:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at com.Term.<init>(Term.java:97)
at com.Term.substituteVariables(Term.java:251)
at com.Term.substituteVariables(Term.java:247)
at com.Term.substituteVariables(Term.java:247)
at com.TermPredTestArch.main(TermPredTestArch.java:40)
Run Code Online (Sandbox Code Playgroud)
有问题的方法,substituteVariables,基本上是一个复制构造函数,略有修改:它接受一个绑定映射,并递归遍历调用它的Term对象,沿途查找变量并将它们交换出来实例.奇怪的是,它似乎只是在我离开时的昨晚工作(虽然我没有广泛测试),但现在拒绝玩得很好; 我没有做过任何实质性的修改.
相关代码如下(第232-252行):
232 /** Returns a new Term with the appropriate bindings substituted */
233 public Term substituteVariables(Map<Variable, Symbol> bindings) {
234 ArrayList<Symbol> args = this.getArgs();
235 ArrayList<Symbol> newArgs = new ArrayList<Symbol>();
236 Set<Variable> vars = this.getVars();
237 Set<Variable> bindingKeys = bindings.keySet();
238 for(Symbol s: args) {
239 // if s is a Variable, check to see if it has a substituion, and
240 // if so, swap it out
241 if(s instanceof Variable) {
242 if(bindingKeys.contains(s)) newArgs.add(bindings.get(s));
243 else newArgs.add(s);
244 // if s is a Term, add it and recursively substitute any variables
245 // it has within the current set of bindings
246 } else if(s instanceof Term) {
247 newArgs.add(((Term) s).substituteVariables(bindings));
248 // if s is just a symbol, simply add it to the args
249 } else newArgs.add(s);
250 }
251 return new Term(this.getName(), newArgs);
252 }
Run Code Online (Sandbox Code Playgroud)
编辑:这是Term的构造函数:
public Term(String n, ArrayList<Symbol> a) {
super(n);
args = a;
HashSet<Variable> varsToAdd = new HashSet<Variable>();
for(Symbol s: a) parseArg(s.toString());
}
Run Code Online (Sandbox Code Playgroud)
那是被调用的实际构造函数,而不是我认为被调用的构造函数.事实上,根据Kal的回答,这违反了foreach循环并发规则.
从我已经完成的研究中,我知道ConcurrentModificationException通常是由多个线程在没有同步的情况下同时迭代/修改Collection引起的,但是我没有故意的并行性,也没有在类中的任何其他地方,或者使用它的测试代码.否则,我不完全确定.该类的javadoc提到它也可能是由迭代器同时迭代和修改Collection引起的,但我不认为我也是这样做的; 我只是观察迭代的Collection并使用它的信息来构建另一个Collection.这是否违反了并发法规?
您可能提供的任何指针都将非常感激!对于任何严重违反Java礼仪或风格的行为,我也会先发制人地道歉(请随意指出这些内容!).
谢谢
Kal*_*Kal 12
在使用for循环迭代ArrayList时修改ArrayList时发生ConcurrentModificationException.
正确执行此操作的方法是使用迭代器添加/删除方法.
以下是API的相关文档 -
这个类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对list进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出ConcurrentModificationException.因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险.