2013-06-12 71 views
0

問題的一些背景:我有一個類負責通知各種客戶有關服務的變化。所以它有幾個HashMaps的偵聽器,並在需要時迭代這些HashMaps來調用它們的方法(它也有方法來添加/刪除這些HashMaps中的偵聽器)。問題是,我經常需要刪除某些偵聽器,而他們正在迭代... ,我需要能夠從循環外部調用remove(...)方法。迭代和刪除都發生在同一個線程上。該類的實例同時修改/刪除HashMap中沒有迭代器的條目

class SomeClass { 
    Map<Listener, Boolean> listeners = new HashMap<Listener, Boolean>(); 

    void add(Listener listener) { 
     listeners.put(listener, true); 
    } 

    void remove(Listener listener) { 
     listeners.remove(listener); 
    } 

    void notifyListeners() { 
     Iterator<Map.Entry<Listener, Boolean>> it = listeners.entrySet().iterator(); 
     while (it.hasNext()) { 
      it.next().getKey().onDo(); 
     } 
    } 

    static interface Listener{ 
     void onDo(); 
    }} 

我要調用remove(...)(以及如何失敗)的方式:

final SomeClass someClass = new SomeClass(); 

    Listener a = new Listener(){ 
     @Override 
     public void onDo() { 
      someClass.remove(this); 
     } 
    }; 

    Listener b = new Listener(){ 
     @Override 
     public void onDo() { 
      someClass.remove(this); 
     } 
    }; 

    Listener c = new Listener(){ 
     @Override 
     public void onDo() { 
      someClass.remove(this); 
     } 
    }; 

    someClass.add(a); 
    someClass.add(b); 
    someClass.add(c); 

    someClass.notifyListeners(); 
    // java.util.ConcurrentModificationException 

有任何把戲做到這一點?

回答

1

你的問題是使用ConcurrentHashMap候選人。只需將您的地圖定義替換爲ConcurrentHashMap

Map<Listener, Boolean> listeners = new ConcurrentHashMap<Listener, Boolean>(); 
+0

是的,它的工作。順便說一句,什麼時候進行拆除?我可以確定在電話回覆時刪除了條目** a **嗎? –

+0

刪除實時發生,但迭代發生在收集快照上。閱讀@finejustice共享的文檔。我會幫你的 :) – vineet