2016-11-18 29 views
0

我讀過很多關於這個問題的SO問題,但我不明白爲什麼我有一個java.util.ConcurrentModificationException的Android ConcurrentModificationException的上設置

在一類我有這樣的:

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

所有操作在mRequest對象通過synchronized聲明這樣的包圍:

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

      handleOrder(sOrder; 
     } 
    } 
} 

我得到的錯誤是:

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

任何想法爲什麼?同步語句不應該阻止併發問題嗎?

回答

1

它看起來像你的方法調用來添加/刪除RequestOrders從集可能正在發生,而你仍然在迭代mRequest集。因此,當你仍然在迭代導致錯誤時,mRequest集的大小正在改變。要解決這個問題,您可以:

1 - 創建一個臨時集,其中包含要添加到mRequest的所有對象。一旦完成循環遍歷mRequest集合中的所有對象,請將臨時集合中的所有對象添加到mRequest集合中。

2-使用併發HashMap。

這裏是你如何使用第一種方法的例子:

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

感謝。我是否應該特別注意刪除'mRequests.remove(order);'? – Favolas

+1

是的,對Set的任何修改將導致Set size改變,(remove或add)將需要以類似的方式處理。祝你好運 :) – sparkplug

相關問題