【发布时间】:2022-01-05 07:09:32
【问题描述】:
optaplanner-bom 版本 7.45.0.Final.
@PlanningEntity
public class Task {
@PlanningVariable(valueRangeProviderRefs = "timeGrainRange")
private TimeGrain startingTimeGrain;
@CustomShadowVariable(variableListenerClass = DurationUpdatingVariableListener.class,
sources = { @PlanningVariableReference(variableName = "startingTimeGrain") })
private Long durationInGrains;
......
在 DurationUpdatingVariableListener 类中:
public void afterVariableChanged(ScoreDirector scoreDirector, Task e) {
if (null == e.getStartingTimeGrain()) {
return;
}
Schedule s = (Schedule)scoreDirector.getWorkingSolution();
List<Task> tasksToBeUpdated = s.getTasksToBeUpdated(e); // calculate all updates
for (Task t: tasksToBeUpdated) {
scoreDirector.beforeVariableChanged(t, NAME_DURATION);
t.setDurationInGrains(convertToGrain(t.getDurationInSecs()));
scoreDirector.afterVariableChanged(t, NAME_DURATION);
}
}
逻辑是,当一个任务的startingTimeGrain改变时,会影响一些任务的时长。问题是,当变量“tasksToBeUpdated”只包含一个任务时,没有错误。当它包含多个任务时,出现以下错误:
ERROR 30844 --- [pool-1-thread-1] o.o.c.impl.solver.DefaultSolverManager : Solving failed for problemId (1).
java.lang.IllegalStateException: The move thread with moveThreadIndex (3) has thrown an exception. Relayed here in the parent thread.
at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:147) ~[optaplanner-core-7.45.0.Final.jar:7.45.0.Final]
at org.optaplanner.core.impl.constructionheuristic.decider.MultiThreadedConstructionHeuristicDecider.forageResult(MultiThreadedConstructionHeuristicDecider.java:186) ~[optaplanner-core-7.45.0.Final.jar:7.45.0.Final]
......
Caused by: java.lang.IllegalStateException: VariableListener corruption after completedAction (Undo(id=1, ...., startingTimeGrain=null {null -> {"grainIndex":1,"id":1}})):
The entity (id=2, ..., startingTimeGrain=1)'s shadow variable (Task.durationInGrains)'s corrupted value (4) changed to uncorrupted value (3) after all VariableListeners were triggered without changes to the genuine variables.
Maybe the VariableListener class (DurationUpdatingVariableListener) for that shadow variable (Task.durationInGrains) forgot to update it when one of its sources changed.
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.assertShadowVariablesAreNotStale(AbstractScoreDirector.java:545) ~[optaplanner-core-7.45.0.Final.jar:7.45.0.Final]
......
可以肯定的是,Task.setDurationInGrains() 只在 afterVariableChanged() 中被调用。为什么会发生错误? Here 是Schedule.getTasksToBeUpdated(Task task)的代码。
【问题讨论】:
-
你也可以显示
Schedule.getTasksToBeUpdated(Task task)body 吗? -
将方法的链接附加到问题中。
标签: optaplanner