It's been awhile since I wrote some Java so this code is probably crap:
synchronized (this){
for (IAsyncCb cb : this.getOnDrainCbs()) {
cb.run(this);
}
}
I am getting this warning:
Exception in thread "Thread-4" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891)
at org.ores.Queue$1.lambda$done$0(Queue.java:310)
at java.base/java.lang.Thread.run(Thread.java:844)
Really, Java should print something WarningEvent instead of Exception, since it doesn't stop execution, but that's besides the point. This seems to be the culprit:
public void onDrain(IAsyncCb cb) {
this.drainCBs.add(cb);
}
but it's working with a synchronized collection:
private List<IAsyncCb> drainCBs = Collections.synchronizedList(new ArrayList<>());
but if I change it to:
public synchronized List<IAsyncCb> getOnDrainCbs() {
return this.drainCBs;
}
public void onDrain(IAsyncCb cb) {
this.getOnDrainCbs().add(cb);
}
then I no longer get the ConcurrentModificationException
. Anybody know why using a synchronized getter would prevent the exception, even when it's already a synchronized list?
In other words, I would have assumed that using Collections.synchronizedList()
would have prevented this kind of exception/warning, and would have obviated the need for a synchronized getter.