我有一个带有比较器的TreeSet
:
private final TreeSet<TimedTask> sortedEvents;
public TimedUpdatableTaskList(){
Comparator<TimedTask> comparator = new TimedTaskComparator();
sortedEvents = new TreeSet<>(comparator);
}
该类实现了一种向集合中添加元素的方法:
public void add(TimedTask task) {
synchronized (sortedEvents) {
sortedEvents.add(task);
log.info("Add task {}:{}", task.getClass().getName(), task);
}
}
添加的TimedTask
如下:
class AIRepairTask extends TimedTask {
private AsyncEventBus clientServerEventBus;
private final IShip ship;
private final IShipyard shipyard;
public AIRepairTask(LocalDateTime executionTime, IShip ship, IShipyard shipyard) {
super();
setExecutionTime(executionTime);
this.ship = ship;
this.shipyard = shipyard;
}
@Override
public void run() {
ship.repair();
shipyard.removeCompletedRepair(ship);
ship.setAvailable(true);
clientServerEventBus.post(new RepairFinishedEvent(ship));
}
}
然后有一种方法可以遍历元素并最终将其删除:
public void handleClockTick(ClockTick event) {
LocalDateTime now = date.getCurrentDate();
int nbHandledTasks = 0;
synchronized (sortedEvents) {
int initialSize = sortedEvents.size();
boolean moreEvents = true;
while(moreEvents && !sortedEvents.isEmpty()) {
TimedTask task = sortedEvents.first();
Preconditions.checkNotNull(task.getExecutionTime(), "The exectution time of the task may not be null");
if (task.getExecutionTime().isBefore(now)) {
try {
task.run();
boolean removed = sortedEvents.remove(task);
Preconditions.checkArgument(removed, "The Task "+task+" was not removed.");
nbHandledTasks++;
} catch (Exception e) {
e.printStackTrace()
}
} else {
moreEvents = false;
}
}
Preconditions.checkArgument(initialSize - nbHandledTasks == sortedEvents.size(), "List size did not become smaller: initial size "+initialSize+", handled tasks "+nbHandledTasks+", actual list size: "+sortedEvents.size());
}
}
由于基本部分都包裹在一个同步块中,因此在迭代元素时该集合不应更改。
考虑到try
块中没有异常,最后的前提条件检查永远不会失败,但这就是发生的情况:
java.lang.IllegalArgumentException: List size did not become smaller: initial size 41, handled tasks 2, actual list size: 41
这怎么发生?