java.util.AbstractList$Itr.checkForComodification Triple Events
Ich einen server laufen lassen, und es hat einen event-handler, mit einem timing-system
Bei mir laufen 3 von Ihnen in einer Reihe, es gibt diese Ausnahme
Exception in thread "Thread-8" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at EventManager.run(EventManager.java:77)
at java.lang.Thread.run(Thread.java:662)
hier ist die Methode, dass die Frage kommt:
EventManager.getSingleton().addEvent( new Event() {
public void execute(EventContainer c) {
p.createProjectile(p.absY, p.absX, offsetY, offsetX, 1166, 43, 31, 70, p2.playerId);
c.stop(); //stops the event from running
}
}, 950); //in ms (1 second = 1000 ms)
EventManager.getSingleton().addEvent( new Event() {
public void execute(EventContainer c) {
p2.applyDAMAGE(misc.random(25));
c.stop(); //stops the event from running
}
}, 1300); //in ms (1 second = 1000 ms)
p.secondsTillNextDfsSpecial = 120;
EventManager.getSingleton().addEvent( new Event() {
public void execute(EventContainer c) {
p.secondsTillNextDfsSpecial--;
if (p.secondsTillNextDfsSpecial == 0) {
p.canPerformDfsSpecial = true;
c.stop(); //stops the event from running
}
}
}, 1000); //in ms (1 second = 1000 ms)
import java.util.ArrayList;
import java.util.List;
/**
* Manages events which will be run in the future.
* Has its own thread since some events may need to be ran faster than the cycle time
* in the main thread.
*
* @author Graham
*
*/
public class EventManager implements Runnable {
/**
* A reference to the singleton;
*/
private static EventManager singleton = null;
/**
* A list of events that are being executed.
*/
private List<EventContainer> events;
/**
* Initialise the event manager.
*/
private EventManager() {
events = new ArrayList<EventContainer>();
}
/**
* The event manager thread. So we can interrupt it and end it nicely on shutdown.
*/
private Thread thread;
/**
* Gets the event manager singleton. If there is no singleton, the singleton is created.
* @return The event manager singleton.
*/
public static EventManager getSingleton() {
if(singleton == null) {
singleton = new EventManager();
singleton.thread = new Thread(singleton);
singleton.thread.start();
}
return singleton;
}
/**
* Initialises the event manager (if it needs to be).
*/
public static void initialise() {
getSingleton();
}
/**
* The waitFor variable is multiplied by this before the call to wait() is made.
* We do this because other events may be executed after waitFor is set (and take time).
* We may need to modify this depending on event count? Some proper tests need to be done.
*/
private static final double WAIT_FOR_FACTOR = 0.5;
@Override
/**
* Processes events. Works kinda like newer versions of cron.
*/
public synchronized void run() {
long waitFor = -1;
List<EventContainer> remove = new ArrayList<EventContainer>();
while(true) {
//reset wait time
waitFor = -1;
//process all events
for(EventContainer container : events) {
if(container.isRunning()) {
if((System.currentTimeMillis() - container.getLastRun()) >= container.getTick()) {
container.execute();
}
if(container.getTick() < waitFor || waitFor == -1) {
waitFor = container.getTick();
}
} else {
//add to remove list
remove.add(container);
}
}
//remove events that have completed
for(EventContainer container : remove) {
events.remove(container);
}
remove.clear();
//no events running
try {
if(waitFor == -1) {
wait(); //wait with no timeout
} else {
//an event is running, wait for that time or until a new event is added
int decimalWaitFor = (int)(Math.ceil(waitFor*WAIT_FOR_FACTOR));
wait(decimalWaitFor);
}
} catch(InterruptedException e) {
break; //stop running
}
}
}
/**
* Adds an event.
* @param event The event to add.
* @param tick The tick time.
*/
public synchronized void addEvent(Event event, int tick) {
events.add(new EventContainer(event,tick));
notify();
}
/**
* Shuts the event manager down.
*/
public void shutdown() {
this.thread.interrupt();
}
}</code></pre>
- Poste bitte den code für
EventManager
. Auch, es wäre schön, wenn Sie reduzieren den code, dass ist irrelevant für das problem. Sie haben nur ein thread in deine app? Ist das eine Swing-Anwendung? - Im Grunde sind Sie machen änderungen an einer Sammlung während der Iteration über es, aber das passiert in
EventManager
code. - Zeile 77 mit Bezug auf eine Erhebung. Und, vermutlich, dass Sie nicht mit einem synchronisierten Sammlung. Das beheben.
- Hinzugefügt wurde die Klasse eventmanager, lassen Sie mich wissen, ob weitere Hilfsmittel notwendig sind.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ok, ich sehe zwei Probleme:
Ihre Veranstaltungen
List
ist nicht synchronisiert und Sie sind der Zugriff aus verschiedenen threads (inEventManager
und zweiten in das erste Stück code mitaddEvent()
).In dieser Schleife:
Iteration durch Ereignisse
List
und Sie hinzufügen kann neue Elemente während der iteration. Ich gehe davon ausaddEvent()
ist das hinzufügen neuer Elemente zu dieser Liste, also im Grunde sollte man es nicht nennen, die während dieser iteration.Beide dieser Probleme können gelöst werden durch die Verwendung Die Klassen CopyOnWriteArrayList ermöglicht den sicheren Zugriff von gleichzeitigen threads und sicher das hinzufügen neuer Elemente während der iteration (jedoch neue Elemente werden "sichtbar", nur in der nächsten iteration).
Lösung:
List
und wahrscheinlich haben sollteList<Event>
oderList<EventContainer>