2011-01-13 21 views
0

Die andere Frage ist über synchronisiert. Ich habe auch eine run() in Klasse Note, weil ich jedes Element in Notizen alle 5 Minuten ausgeben möchte. Aber ich bekomme immer eine Ausnahme: java.util.ConcurrentModificationException, wenn ich versuche, weitere Meetings in main zu machen. so i applay auf die Liste Notizen synchronisiert, die eine neue Sitzung hinzugefügt werden können, wenn ich über notes.My run-Methode wie folgt durchlaufen:Ist es eine gute Möglichkeit zu verhindern, ConcurrentModificationException

Ist es richtig, Art und Weise hier auf Liste Notizen ConcurrentModificationException zu verhindern synchronisiert? (In meinem Programm works.I es jetzt nie diese Ausnahme erhalten)

A Meeting Klasse und Hinweis Klasse kann gefällt das:

public class Meeting{ 

    public Meeting(Note note_1,Note note_2){ 

       note_1.addElement(this); 

       note_2.addElement(this);} 

       //another method hier 

        } 

public class Note implements Runnable{ 

    public final List<Meeting> notes = new ArrayList<Meeting>(); 

    public void addElement(Meeting n){ 

       entries.add(n); 
       } 

    @Override 

    public void run(){ 
      while(true) { 
      for(Meeting n : notes){ 

       System.out.println(n.toString);} 

       } 

      try{ Thread.sleep(10);} 

      } 

      } 
      } 

Ich bekomme immer Ausnahmefehler über Ausnahme: java.util.ConcurrentModificationException, wenn ich versuche, mehr Meeting in Haupt zu machen, so dass ich ändere eine littel in der Klasse Hinweis, mag dies:

private static final List<Entry> entries = Collections.synchronizedList(new ArrayList<Entry>()); 

und in run()

@Override 
public void run() { 
    while(true){ 
     synchronized(notes){ 
      for(Entry n : entries){ 
       //do something 
       } 
      } 
      try { 
       Thread.sleep(10); 
     } catch (InterruptedException e) { 
      } 
    } 
    } 

}

+1

Während Ausnahme zu werfen Was Sie hierher gebracht hat, sollte ich auch darauf hinweisen, dass Ihre Logik nicht ideal ist, da [Sie sollten während der Konstruktion keinen Verweis auf "dieses" veröffentlichen (http://www.ibm.com/developerworks/java/library) /j-jtp0618.html) wenn Sie mehrere Threads verwenden möchten, da es Invarianten brechen kann, die "immer" halten müssen. Wenn Sie Ihren Code korrekt und konsistent einbetten, wird die Lesbarkeit um ein erstaunliches Maß verbessert. –

+0

Dank Andrzej und Sorry, dass mein Code nicht richtig gepostet wird. Multiple Threads führt nicht zu ConcurrentModificationException in meinem Programm. Es tritt auf, wenn ich über die Liste in der Klasse Note iteriere und vielleicht ein neues Meeting-Objekt sich der Liste hinzufügen möchte – echo

Antwort

4

Vom javadoc

Beachten Sie, dass diese Ausnahme nicht immer zeigen, dass ein Objekt von einem anderen Thread gleichzeitig modifiziert wurde. Wenn ein einzelner Thread eine Sequenz von Methodenaufrufen ausgibt, die den Vertrag eines Objekts verletzen, kann das Objekt diese Ausnahme auslösen. Wenn beispielsweise ein Thread eine Auflistung direkt ändert, während sie die Auflistung mit einem Fail-Fast-Iterator iteriert, löst der Iterator diese Ausnahme aus.

Das bedeutet, dass Sie Ihre Sammlung nicht in einer Schleife ändern und gleichzeitig im selben Thread darüber iterieren.

+0

+1, das ist es genau. Eine Möglichkeit, dieses Problem zu umgehen, besteht darin, eine * Kopie * der betreffenden Sammlung zu erstellen und dann über die Kopie zu iterieren (so dass Elemente ohne Probleme zum Original hinzugefügt werden können). Aber normalerweise ist es ein Zeichen dafür, dass der logische Fluss nicht so klar ist, wie er sein könnte. Daher lohnt es sich darüber nachzudenken, warum Sie während der Iteration mutieren und wie Sie sonst Ihre Ziele erreichen könnten. –

0

Lesen Sie, was @Navi geschrieben hatte.

Auf den Punkt gebracht - NIEMALS Elemente einer Sammlung für jede Schleife entfernen/hinzufügen.

Ich hatte einmal diese Art von Problem und ich entschied mich zu verwenden http://code.google.com/p/google-collections/ Es gibt einige Karten-/Filterfunktionen dort (wenn ich mich erinnere, dass Methoden in Collections2 Bibliothek waren).

Wenn Sie nicht bereit sind, die Dinge richtig zu machen, können Sie immer die Old-School-Iterator-Technik verwenden.

+0

Sie können Elemente aus einer Liste entfernen (während der Iteration), wenn Sie mit der Iterator-Schnittstelle iterieren und die Methode remove() des Iterators verwenden. Das Hinzufügen von Elementen wird von der Iterator-Schnittstelle nicht unterstützt. – Atticus

0

Ich habe eine CopyOnWriteArrayList zuvor verwendet, als ich auf diese Art von Problem stieß.

Dies macht eine vollständige Kopie des zugrunde liegenden Arrays für jeden schreiben, so dass es nicht sehr effizient ist, aber ich habe es sehr nützlich für bestimmte Umstände gefunden (z.eine Klasse, die Benachrichtigung zu einigen anderen Klassen Fachveranstaltung verwaltet)

Dieses Array nie während der Lebensdauer des Iterators ändert, so Interferenz ist unmöglich und der Iterator nicht gewährleistet ist ConcurrentModificationException

Verwandte Themen