2016-11-18 9 views
0

Ich habe viele der SO Fragen zu diesem Thema gelesen, aber ich kann nicht verstehen, warum ich ein java.util.ConcurrentModificationException mit binAndroid ConcurrentModificationException auf Set

In einer Klasse Ich habe dies:

private Set<RequestOrders> mRequests = new HashSet<>(); 
private final Object lock = new Object(); 

Alle Operationen

public void handleOrder(RequestOrders order) { 
    synchronized (lock) { 
     if (!mRequests.contains(order)) { 
      final sOrder = saveOrderOnDB(order); 
      mRequests.add(sOrder); 

      handleOrder(sOrder; 
     } 
    } 
} 

ich erhalte den Fehler in dieser: auf das mRequest Objekt wird durch eine synchronisierte Anweisung wie folgt umgeben

void notifyOrder(int type) { 
    if (!mPause) { 
     synchronized (lock) { 
      for (RequestOrders request : mRequests) { // Error here while iterating 
       if (.....) { 
        redirectOrders(request); 
       } else if (....) { 
        ...... 
        startService(.....); 
       } 
      } 
     } 
    } else { 
     ..... 
    } 
} 

Irgendeine Idee warum? Sollten die synchronisierten Anweisungen keine Nebenläufigkeitsprobleme verhindern?

Antwort

1

Es sieht so aus, als ob Ihre Methodenaufrufe zum Hinzufügen/Entfernen von RequestOrders aus dem Set möglicherweise ausgeführt werden, während Sie noch über den mRequest-Satz iterieren. Daher ändert sich die Größe des mRequest-Satzes, während Sie noch iterieren, was den Fehler verursacht. Um dies zu umgehen, können Sie entweder:

1 - Erstellen Sie eine temporäre Menge, die alle Objekte enthält, die mRequest hinzugefügt werden sollen. Wenn Sie mit dem Schleifen aller Objekte im mRequest-Set fertig sind, fügen Sie alle Objekte im temporären Set zum mRequest-Set hinzu.

2- Verwenden Sie eine gleichzeitige HashMap. Hier

ist ein Beispiel, wie Sie den ersten Ansatz verwenden:

private Set<RequestOrders> mRequests = new HashSet<>(); 
private Set<RequestOrders> backlog = new HashSet<>(); 

public void handleOrder(RequestOrders order) { 
    synchronized (lock) { 
     if (!mRequests.contains(order)) { 
      final sOrder = saveOrderOnDB(order); 
      backlog.add(sOrder); 
      handleOrder(sOrder); 
     } 
    } 
} 

void notifyOrder(int type) { 
    if (!mPause) { 
     for (RequestOrders request : mRequests) { // Error here while iterating 
      if (.....) { 
       redirectOrders(request); 
      } else if (....) { 
       ...... 
       startService(.....); 
      } 
     } 
     mRequests.addAll(backlog); 
     backlog.clear(); 
    } else { 
     ..... 
    } 
} 
+0

Dank. Sollte ich besondere Sorgfalt darauf verwenden, 'mRequests.remove (order) zu entfernen;'? – Favolas

+1

Ja, alle Änderungen am Set, die zur Änderung der Set-Größe führen, (entfernen oder hinzufügen), müssen auf ähnliche Weise behandelt werden. Viel Glück :) – sparkplug

Verwandte Themen