0

Ich halte eine Karte von Objekten und jedes Mal, wenn ein Objekt hinzugefügt wird, müssen alle anderen Objekte in der Karte über das neue Objekt benachrichtigt werden und umgekehrt. Diese Objekte laufen auf eigene Thread Prozess (jeder ist gestartet von einem main) kann eine Methode aufrufen, die sie in die Karte fügt, so dass ein Objekt während der Iteration durch Hinzufügen eines vorherigen Objekts hinzugefügt werden kann.Wie man über eine Karte iteriert und gleichzeitig Werte hinzufügt?

Dies ist ein Beispielcode, den ich habe. Hier sind die Objekte, die ich sprach über

class Notifier { 

    String name; 
    Hub hub; 

    Notifier(String name) { 

     this.name = name; 
     hub.add(this); 
    } 

    void acknowledge(String name) { 

     System.out.println(this.name + " was notified of " + name); 
    } 
} 

Hier ist die Sache, die die Karte

public class Hub { 

    ConcurrentMap<String, Notifier> map = new ConcurrentHashMap<>(); 

    void add(Notifier notifier) { 

     map.putIfAbsent(notifier.name, notifier); 

     Iterator<Entry<String, Notifier>> it = map.entrySet().iterator(); 
     while (it.hasNext()) { 
      Entry<String, Notifier> entry = it.next(); 
      if (!entry.getKey().equals(notifier.name)) { 
       entry.getValue().acknowledge(notifier.name); 
       notifier.acknowledge(entry.getKey()); 
      } 
     } 
    } 
} 

ich ConcurrentHashMap versuchte hält aber es muss nicht so sein. Mein Problem ist, dass die Ergebnisse, die ich bekomme, jedes Objekt mehr als einmal über die anderen benachrichtigt werden, wenn ich ihre Threads zusammen starten. Ich bekomme

notifier1 von notifier2
notifier1 mitgeteilt wurde von notifier2
notifier1 mitgeteilt wurde von notifier3
notifier1 mitgeteilt wurde von notifier3
notifier1 mitgeteilt wurde von notifier4
notifier1 mitgeteilt wurde von notifier4

mitgeteilt wurde

und das gleiche für die anderen. Wenn ich sie 1 nach dem anderen starten, so lasse ich jedes Finish Hinzufügen ich das richtige Ergebnis

notifier1 mitgeteilt wurde von notifier2
notifier1 mitgeteilt wurde von notifier3
notifier1 mitgeteilt wurde erhalten von notifier4

und ähnlich für die anderen.

Ich weiß, dass diese Karte, die ich gewählt habe, keine Garantie für die Aktualisierung des Iterators beim Hinzufügen (Put) von Werten, also denke ich, ist, warum es passiert. Wie auch immer, ich weiß, dass es bei den oben genannten Experimenten einige Gewindegänge gibt.

Wie mache ich es so, dass jedes Objekt genau einmal von allen anderen benachrichtigt wird? Vielleicht ist diese gleichzeitige Karte nicht gut und ich muss etwas synchronisieren? Die Reihenfolge der Additionen ist mir egal.

+0

Welche Arten von Objekten sind das? Gibt es einen guten Grund, sie zu unabhängigen Threads zu machen, anstatt einen Callback-Ansatz zu verwenden? – chrylis

+0

@chrylis es ist wie Clients und ein Server. Jeder Client, der hereinkommt, wird über alle anderen Clients benachrichtigt, und sie werden darüber benachrichtigt. Ist das nicht schon eine Art Callback, weil der Hub Methoden für das Notifier-Objekt aufruft? Entschuldigung, wenn ich nicht verstehe. – Mark

+0

Sortierung, aber Sie haben ausdrücklich gesagt, dass sie "auf ihren eigenen Threads laufen", die nicht mit dem Code übereinstimmen, den Sie hier gepostet haben. – chrylis

Antwort

0

Ich denke, der Fehler ist ziemlich einfach. Sie brechen die Benachrichtigung im Falle eines doppelten Notifiers nicht ab.

public class Hub { 

    ConcurrentMap<String, Notifier> map = new ConcurrentHashMap<>(); 

    void add(Notifier notifier) { 

     if (map.putIfAbsent(notifier.name, notifier) == null) { 

      Iterator<Entry<String, Notifier>> it = map.entrySet().iterator(); 
      while (it.hasNext()) { 
       Entry<String, Notifier> entry = it.next(); 
       if (!entry.getKey().equals(notifier.name)) { 
        entry.getValue().acknowledge(notifier.name); 
        notifier.acknowledge(entry.getKey()); 
       } 
      } 
     } 
    } 
} 
+0

Aber es gibt nicht mehrere Starts desselben Notifier - jeder ruft die Add-Methode genau einmal auf. Ich werde meinen Code aktualisieren, es scheint, dass ich auf tieferem Wasser bin, als ich ursprünglich dachte. – Mark

+0

Wenn Sie mehrere von ihnen mit dem gleichen Namen haben, z. Derselbe Schlüssel, dann Map verhindert Duplikate, aber Benachrichtigungen werden trotzdem gesendet. – Max

+0

Ich habe nicht mehrere mit dem gleichen Namen. Der Konstruktor erhält einen eindeutigen Namen. – Mark

Verwandte Themen