# java.util.ConcurrentModificationException vermeiden?



## rhanarion (28. Nov 2009)

Hallo,

ich habe mir mal das Spiele Tutorial von Quaxli angesehen und wollte nun mal ein wenig damit rumspielen. Da ich gerne mit Vektoren im 2D Raum arbeiten würde wollte ich mir eine Vektorklasse schreiben und diese als "Kraft" an einem Spielerobjekt nutzen. Dieses verwaltet alle auf ihm wirkende Kräfte in einem Vektor (?? aus java.util). Über diese wird dann iteriert um sie zu verkleinern (Reibung). Immer wenn ich nun im Spiel hochspringe (also einen Vektor zur Liste hinzufüge) klappt es super. Die Figur springt und fällt dann langsam zurück (sobald der Sprungvektor klein genug wird um durch den Gravitationsvektor ausgeglichen zu werden). Doch ein paar cm über dem Boden stürzt meine kleine Simulation mit folgendem Fehler ab:


```
Exception in thread "Thread-2" java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
	at java.util.AbstractList$Itr.next(AbstractList.java:420)
	at Player.doLogic(Player.java:59)
	at GamePanel.doLogic(GamePanel.java:133)
	at GamePanel.run(GamePanel.java:79)
	at java.lang.Thread.run(Thread.java:613)
```

Gamepanel implementiert das Runnable Interface, run ist mehr oder weniger aus dem Tutorial:


```
public void run()
	{
		while (gameRunning) {
	
			computeDelta();
			
			if (isStarted()) {
				checkKeys();
				doLogic();
				moveObjects();
			}
				
			repaint();
				
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
			}
		}
	}
```

in do Logic wird nur die doLogic Funktion des Spielers aufgerufen. Hier passiert folgendes:

[JAVA=56]
public void doLogic(long delta) 
	{
		synchronized (dimishingForces) {
			for (ForceVector2D vector:dimishingForces)
			{
				if (vector.length() != 0) {
					try {
						vector.trimTo(vector.length() - (reibung * delta) / ((long) 1e9));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				if (vector.length() <= 0.05) {
					dimishingForces.remove(vector);
				}
			}
		}
	}
[/code]

Der ForceVektor2D ist einfach von mir mit ein paar Hilfsfunktionen wie length, trimTo etc. Synchronized habe ich drumherum geschrieben aus Verzweiflung quasi .

Ich habe noch nicht wirklich viel mit paralellen Threads gemacht und mich wundert diese Exception ehrlich gesagt. Ich dachte ich starte nur einen Thread und der läuft? Ich wüsste nicht welcher 2. Thread gleichzeitig auf die Liste zugreifen sollte?

Gruß,

rhan


----------



## javimka (28. Nov 2009)

Das Problem ist deine Art, wie du durch die Liste interierst: [c] for (ForceVector2D vector:dimishingForces)[/c]
Wenn du dann ein Element mit remove() löschst, dann funkst du dem Iterator dazwischen und es gibt diese Exception.
Mach es so: 

```
for (int i=0;i<dimishingForces.size();i++) {
   ForceVector2D vector = dimishingForces.get(i);
   ...
```

Statt Vector solltest du vielleicht Besser ArrayList verwenden.


----------



## rhanarion (28. Nov 2009)

Ha, vielen Dank! Mein kleiner Sprite winkt dir glücklich zu, endlich kann er springen .

ArrayList werde ich mir mal ansehen. Der Code war bis jetzt sowieso mehr ein Physik Experiment als was sinnvolles. Ich werde nun mal Dinge wie Beschleunigung etc einbauen und melde mich wenns da schlimme Probleme gibt


----------



## G_ast_ (3. Apr 2010)

Hallo, ich habe genau das selbe Problem jedoch wollte ich mich jetzt nicht neu anmelden um nur ein Post/Topic zu schreiben.
Die Lösung ist mir auch klar und es funktioniert zur zeit, doch was ich mich noch frage ist warum gibt er bei der exception "thread-2" an?
Bei mir habe ich auch nur einen thread gestartet in diesem ändere ich dann etwas an meiner hashmap im gleichen thread rufe ich die repaint methode auf. In der dazugehörigen paintComponent Methode wird die HashMap durch iteriert und dort trat auch der fehler auf. Stellt nun das repaint den "thread-2" dar oder der Iterator?

Hoffe das ist verständlich


----------



## Marco13 (3. Apr 2010)

Schwer zu sagen. Wenn man nur ein Fenster aufmacht, laufen schon ~10 Threads oder so (die meisten davon sind meistens inaktiv). Du kannst aber deinen eigenen Thread einen Namen geben, das könnte helfen. Schau dir mal die Konstruktoren von "Thread" an....

EDIT: Der Zeichen-Thread heißt aber immer irgendwas mit "Event Dispatch Thread".... der kann es also nicht sein....


----------



## G_ast_ (3. Apr 2010)

Hi, der Thread heißt: AWT-EventQueue-0 ich denke das dieser Thread aufgrund der angabe AWT etwas mit der GUI oberfläsche zu tun hat.


----------



## Empire Phoenix (3. Apr 2010)

Ah da haben wirs!
Gezeichnet wird in einen eigenen Thread nd die logic läuft in einem weiteren so wie ich das oben sehe, und wenn die logic während des zeichnens läuft, dann gibts probleme.

Versuchs mal Testweise mit einem Vector statt der ArrayList, (die ist vom interface fast 100% compatible aber intern synchronisiert), wenns dann geht liegts an synchronisierungs fehlern.


----------



## G_ast_ (4. Apr 2010)

Jo habe daran gestern noch gearbeitet, hatte vorher eine HashMap benutzt (die ich eigentlich nicht brauchte, naja) und in der meiner Logik elemente hinzugefügt und beim zeichnen ausgelesen um den inhalt der hashmap darzu stellen.
Eine Lösung ist jetzt das ich um die iteration beim zeichnen einen synchronized block gebaut habe um die hashmap zu synchronisieren.
Ist zwar ein kleiner flaschen hals aber es sind auch nur begrenzt daten enthalten deswegen wirkt es sich nicht auf die peformance aus.
Wollte aber sowieso die HashMap zurück in eine ArrayList wandeln, dann werde ich mal Vector benutzen.

danke für die hilfe


----------



## Empire Phoenix (5. Apr 2010)

Es gibt noch eine HashSet oder so, die ist synchronized erlaubt aber keine null
Ansonsten wenn es um durchsatz geht gibt es da noch einige optimierte classen für in java.


----------

