Некоторое время у меня есть проект optaplanner, который распределяет задания по списку рабочих с использованием различных свойств оценки, написанных на java. Довольный тем, как это работает, я решил обновить с 7.7.0 до 7.9.0, включить новую опцию многопоточности и посмотреть, будет ли она работать быстрее. Однако теперь я получаю следующую ошибку:
Исключение в потоке «Thread-8» java.lang.IllegalStateException: поток перемещения с moveThreadIndex (0) вызвал исключение. Ретранслируется здесь, в родительском потоке. Вызвано: java.lang.IllegalArgumentException: невозможно найти externalObject (... Worker @ 72d2327a). Можно дать классу (класс Worker) аннотацию PlanningId или изменить LookUpStrategyType аннотации PlanningSolution или не полагаться на функциональность, которая зависит от ScoreDirector.lookUpWorkingObject ().
Итак, я попытался добавить @PlanningId к уникальному идентификатору рабочего класса и получил:
Исключение в потоке «Thread-7» java.lang.IllegalStateException: рабочие объекты (Worker @ 4438b624, Worker @ 4438b624) имеют одинаковый идентификатор планирования ((class Worker, 50)). Рабочие объекты должны быть уникальными.
... но похоже, что он сравнивает объект Worker с самим собой, так что, конечно, это тот же идентификатор ????
Возможно, это связано с моим java-кодом в методах назначения / отмены назначения, но я не понимаю, откуда эта проблема, у кого-нибудь есть идеи?
Изменить: Итак, после большой помощи от @ n1ck я дошел до изменения метода в классе @PlanningSolution, который возвращает список Workers для создания новых экземпляров каждый раз, но с теми же значениями. Это изменяет ошибку следующим образом: «... Рабочие объекты (Worker @ 1eba2b4d, Worker @ 67a7ef08) имеют одинаковый идентификатор планирования ...» Таким образом, он больше не сравнивает идентичные экземпляры, но, похоже, сравнивая его с экземпляром из предыдущего вызова. Однако это, по крайней мере, подтверждает, что в возвращаемом списке нет дублирования. Затем я изменил идентификатор планирования на новое (длинное) поле, значение которого всегда увеличивается с последнего созданного экземпляра, то есть идентификаторы рабочих процессов первого вызова равны 1-10, следующего вызова - 11-20 и т. Д. Это полностью обходит ошибку, но теперь ничего не выделяется для Workers. Он выполняет начальную настройку и присваивает значение null, а затем останавливается до тех пор, пока не будет достигнут предел времени на решателе. Я все еще думаю, что это то, что я не установил правильно, но ошибка, возможно, немного отвлекает, однако, как я запрошен, полная трассировка стека, как я вижу, это:
Исключение в потоке «Thread-10» java.lang.IllegalStateException: рабочие объекты (Worker @ 42094cc1, Worker @ 647a1c5c) имеют одинаковый идентификатор планирования ((class Worker, 50)). Рабочие объекты должны быть уникальными. в org.optaplanner.core.impl.domain.lookup.PlanningIdLookUpStrategy.addWorkingObject (PlanningIdLookUpStrategy.java:40) на org.optaplanner.core.impl.domain.lookup.LookUpManager.addWorknerUgobject.java: .core.impl.domain.lookup.LookUpManager.resetWorkingObjects (LookUpManager.java:43) по адресу org.optaplanner.core.impl.score.director.AbstractScoreDirector.setWorkingSolution (AbstractScoreDirector.java:167) в org.optaplanner .score.director.incremental.IncrementalScoreDirector.setWorkingSolution (IncrementalScoreDirector.java:62) в org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution (DefaultSolverScope.java:230) в orpl .AbstractSolver.solvingStarted (AbstractSolver.java:75) в org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted (DefaultSolver.java:210) в org.optaplanner.core.impl.solver.DefaultSolver.solve. : 190) в SolverThre ad.run (SolverThread.java:86)
Изменить: класс @PlanningSolution по запросу:
package code.test.scheduler;
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
import org.optaplanner.persistence.xstream.api.score.buildin.hardmediumsoft.HardMediumSoftScoreXStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@PlanningSolution
public class Planner
{
@ProblemFactCollectionProperty
private java.util.List<Worker> _workerList;
@ValueRangeProvider(id="workerRange")
@ProblemFactCollectionProperty
public java.util.List<Worker> getWorkerList() {
return _workerList;
}
public void setWorkerList(java.util.List<Worker> newWorkerList) {
_workerList = newWorkerList;
}
public int getWorkerListSize() {
return _workerList.size();
}
@ProblemFactCollectionProperty
private int[][] _travelTimes;
@ValueRangeProvider(id="travelTimes")
@ProblemFactCollectionProperty
public int[][] getTravelTimes() {
return _travelTimes;
}
public void setTravelTimes(int[][] newTravelTimes) {
_travelTimes = newTravelTimes;
}
@PlanningEntityCollectionProperty
private java.util.List<Job> _jobList;
public java.util.List<Job> getJobList() {
return _jobList;
}
public void setJobList(java.util.List<Job> newJobList) {
_jobList = newJobList;
}
@XStreamConverter(HardMediumSoftScoreXStreamConverter.class)
private HardMediumSoftScore _score;
@PlanningScore
public HardMediumSoftScore getScore() {
return _score;
}
public void setScore(HardMediumSoftScore score) {
_score = score;
}
}
workingObjects (Worker@4438b624, Worker@4438b624)
да, это дважды один и тот же экземпляр (при условии, что вы не перезаписывалиObjecttoString()
). Какова полная трассировка стека этого второго исключения? - person Geoffrey De Smet   schedule 02.08.2018