2013-06-12 1 views
0

Quelques informations sur le problème: J'ai une classe chargée d'informer divers clients sur les changements de service. Donc, la classe a plusieurs HashMaps d'écouteurs et appelle leurs méthodes en itérant ces HashMaps quand cela est nécessaire (il a aussi des méthodes pour ajouter/supprimer des listeners de ces HashMaps). Le problème est que j'ai souvent besoin d'enlever certains écouteurs pendant qu'ils sont itérés ... et je dois pouvoir appeler la méthode remove (...) depuis l'extérieur de la boucle.L'itération et la suppression s'effectuent sur le même thread. Exemple de la classe:Modification simultanée/suppression de l'entrée de HashMap sans itérateur

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(); 
    }} 

Et la façon dont je veux appeler retirer (...) (et comment cela échoue):

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 

Y at-il astuce pour le faire?

Répondre

1

Votre problème est candidat à l'aide ConcurrentHashMap. Remplacez simplement votre définition de carte par ConcurrentHashMap

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

Oui, cela fonctionne. Au fait, quand l'enlèvement a-t-il lieu? Puis-je être sûr que l'entrée ** a ** a été supprimée lors du retour de l'appel? –

+0

Supprimer se produit en temps réel, mais l'itération se produit sur un instantané de la collecte. Lisez la documentation partagée par @finejustice. Ça aidera :) – vineet

Questions connexes