0

我持有對象的地圖,每次向對象添加對象時,都需要通知地圖中的所有其他對象,反之亦然。對自己 線程 進程中運行這些對象(每一個是由main啓動)可以可以調用的它們添加到地圖,以便一個對象可以迭代期間添加從添加以前的對象引起的方法。如何迭代地圖,同時向其中添加值?

這是一些示例代碼,我有。下面是我上面

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

這裏談論的對象是保存地圖

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

我試圖ConcurrentHashMap的事情,但它並不一定是。我的問題是,我得到的結果是每個對象都被通知不止一次關於其他如果我一起啓動它們的線程。我得到

notifier1被告知notifier2
notifier1的被通報notifier2
notifier1的被通報notifier3
notifier1的被通報notifier3
notifier1的被通報notifier4
notifier1的通知了notifier4

和其他的相同。如果我一後推出他們1,所以我讓每個完成添加我得到正確的結果

notifier1被告知notifier2
notifier1的被通報notifier3
notifier1的通知了notifier4

和其他類似。

我知道,這個地圖我選擇不作任何添加(放)值時,所以我想這就是爲什麼它會發生更新迭代器保證。無論如何,我知道有一些來自上述實驗的線索比賽。

我如何讓這個每個對象都恰好通知1次,所有其他的?也許這個併發映射不好,我需要同步一些東西?我不關心添加的順序。

+0

什麼樣的對象是誰的?是否有強烈的理由讓他們獨立的線程而不是使用回調方法? – chrylis

+0

@chrylis它就像客戶端和服務器。每個進入的客戶端都會收到所有其他客戶端的通知,並且會通知他們。這不是一種回調,因爲中心調用通告對象的方法嗎?對不起,如果我不理解。 – Mark

+0

排序,但你明確表示他們「在自己的線程上運行」,這與你在這裏發佈的代碼不匹配。 – chrylis

回答

0

我認爲錯誤是很容易的。在通知重複的情況下,您不會中止通知。

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

但是沒有多次啓動相同的通知程序 - 每次只調用一次add方法。我會更新我的代碼,看起來我比最初想象的更深。 – Mark

+0

如果你有幾個同名的例如同樣的關鍵,然後地圖防止重複,但通知無論如何發送。 – Max

+0

我沒有幾個同名的。構造函數被賦予一個唯一的名字。 – Mark