2012-01-31 40 views
0

使用此代碼我得到ConcurrentModificationException?我有一個同步(偵聽器)鎖。獲取ConcurrentModificationException但我沒有刪除

private void notifyListeners(MediumRendition rendition) { 
    if (rendition == null) return; 
    synchronized (listeners) { 
     for (RenditionEventListener l : listeners) { 
      if (l.renditionType.equals(rendition.getType()) && l.mediumId == rendition.getMediumId()) { 
       l.listener.onRendition(rendition); 
      } 
     } 
    } 
} 

public void put(String renditionType, long mediumId, MediumRendition rendition) { 
    HashMap<Long, MediumRendition> l = list.get(renditionType); 
    if (l == null) { 
     l = new HashMap<Long, MediumRendition>(); 
     list.put(renditionType, l); 
    } 
    l.put(mediumId, rendition); 
    notifyListeners(rendition); 
} 

public void addRenditionListener(String renditionType, long mediumId, RenditionListener listener) { 
    synchronized (listeners) { 
     listeners.add(new RenditionEventListener(renditionType, mediumId, listener)); 
    } 
} 

01-30 16:47:55.147 6953 6974ÊAndroidRuntime:致命異常:線程1 01-30 16:47:55.147 6953 6974ÊAndroidRuntime:java.util.ConcurrentModificationException 01-30 E:AndroidRuntime:在java.util.ArrayList $ ArrayListIterator.next(ArrayList.java:573) 01-30 16:47:55.147 6953 6974 E AndroidRuntime:at com。 .vos.RenditionList.notifyListeners(RenditionList.java:79) 01-30 16:47:55.147 6953 6974 E AndroidRuntime:at com.t.vos.RenditionList.put(RenditionList.java:41) 01-30 16:47:55.147 6953 6974èAndroidRuntime:。在COM * controllers.OmwController $ 6.run(OmwController.java:212)

解決:顯然我被移除。見下文。

+2

['CME's(docs)](http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html)不一定是由*不同*線程。 – 2012-01-31 01:05:30

+0

還有什麼可以訪問聽衆?它是否也是同步的? – 2012-01-31 01:08:45

+0

...所以如果是這樣的話,怎麼樣? – user123321 2012-01-31 01:09:23

回答

5

該異常表示偵聽器可能已從另一個線程修改過。所以你應該檢查它是否在沒有同步的情況下被修改。

還檢查onRendition()的實現是否從列表中刪除偵聽器,因爲如果不涉及多個線程,這可能是另一個原因。

+0

「還檢查onRendition()的實現是否將列表中的監聽器從列表中移除,因爲如果多個線程不涉及,那麼這可能是另一個原因....」是的,就是這樣。感謝一堆! – user123321 2012-01-31 01:11:43

2

併發是有點棘手。在應用程序的情況下,雖然,你可能看不到,你是不是修改清單,但它取得了一些修改,當你調用

l.listener.onRendition(rendition); 

可能的解決方案如下。

  1. 使用ConcurrentLinkedQueue而不是ArrayList。如果您使用此集合,則不需要編寫同步塊。這是最簡單的解決方案。
  2. 如果1.不起作用,您可以使用CopyOnWriteArrayList而不是ArrayList。當您存儲聽衆時,最好使用CopyOnWriteArrayList而不是ArrayList
+1

+1,用於指出CopyOnWriteArrayList對於聽衆更可取。 – user949300 2012-01-31 16:58:42

相關問題