我正在使用集成到JavaFX GUI中的OptaPlanner解算器来解决调度问题,该GUI解决了每个改进。 由于将其连接到GUI,因此在构造启发式完成后经常会发生此异常。
Exception in thread "Thread-6" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.cloneCollection(FieldAccessingSolutionCloner.java:297)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.process(FieldAccessingSolutionCloner.java:280)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.processQueue(FieldAccessingSolutionCloner.java:273)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.cloneSolution(FieldAccessingSolutionCloner.java:206)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.cloneSolution(FieldAccessingSolutionCloner.java:72)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneSolution(AbstractScoreDirector.java:142)
at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution(DefaultSolverScope.java:198)
at org.optaplanner.core.impl.solver.DefaultSolver.runPhases(DefaultSolver.java:217)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:176)
at no.scheduling.shifts.solver.ShiftOptaPlanner.solve(ShiftOptaPlanner.java:124)
at application.ScheduleSolver.run(ScheduleSolver.java:69)
at java.lang.Thread.run(Thread.java:745)
我的GUI代码会修改收到的解决方案,因为它包含的项目必须以排序的方式显示给用户。
当我使用侦听器bestSolutionChanged()
方法提供的解决方案进行防御性克隆时,问题就会消失。
我在这里做错了什么,或者事件监听器有时可能会获得OptaPlanner使用的有线实例而不是防御性克隆?
我真的想避免克隆步骤,因为我目前可用的克隆功能有限而且速度慢。
编辑:通过一些进一步的调试,我想我能够在OptaPlanner源代码中找出问题(6.4.0 Final)
完成构造启发式阶段后,updateBestSolution()
中的BestSolutionRecaller
方法将fireBestSolutionChanged()
中的相同解决方案实例放在solverScope
中存储:
public void updateBestSolution(DefaultSolverScope solverScope, Solution solution, int uninitializedVariableCount) {
(...)
solverScope.setBestSolution(solution);
(...)
solverEventSupport.fireBestSolutionChanged(solution, uninitializedVariableCount);
}
这个完全相同的实例然后在setWorkingSolutionFromBestSolution
中进行克隆,同时我的GUI线程正在对其中的事件列表进行排序,并在FieldAccessingSolutionClonerRun.cloneCollection()
中迭代事件列表时抛出异常。
猜猜问题的解决方案是克隆到fireBestSolutionChanged()
的解决方案?
我是否偶然发现了一个微妙的错误或者我做错了什么?谢谢。