2012-10-16 60 views
3

我正在尋找支持事件通知的併發地圖,例如我可以註冊一個特定鍵的回調函數,這些鍵是在這個鍵上放置或刪除時調用的。而且,事情不僅是原子性的,而且與ConcurrentHashMap一樣,也表現出了很好的併發性。尋找支持事件的併發地圖

我的第一個嘗試是從ConcurrentHashMap中竊取基於分段的解決方案,並將一些事件註冊表添加到分段類中。但結果比預期的要難。計算段偏移似乎不是那麼簡單。從ConcurrentHashMap中竊取解決方案並不是那麼容易,如果你不明白它是如何工作的(你錯過了一些細節,並且你的東西最終變成了bug)。也許有人知道一些論文解釋了ConcurrentHashMap中的分段解決方案是如何工作的?比我能通過我的方式工作。

只需在我的地圖放置或移除方法中放置一個大的同步塊,以便放入或移除和調用偵聽器都發生在一個同步塊中很容易。但是,這最終會降低併發性,因爲解決方案只是一種具有單個段的ConcurrentHashMap。

我希望有人知道一些地圖或事件註冊表的實現,它可以做我想做的事情,或者鏈接到一些論文,解釋COncurrentHashMap中這種分段算法是如何工作的。

感謝,奧利弗

+0

想想我現在發現了一些有用的東西:http://www.java2s.com/Code/Java/Collections-Data-Structure/AversionofHashtablesupportingconcurrencyforbothretrievalsandupdates.htm這個細分市場解決方案非常簡單,可能足以滿足我的需求。 – OlliP

+0

這會有幫助嗎? http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ForwardingConcurrentMap.html – artfullyContrived

+0

謝謝,從我可以看到這張地圖不允許放置/刪除回調監聽器被添加。 – OlliP

回答

0

最直接的解決辦法是截獲到ConcurrentHashMap調用獲得通過您註冊事件通知。這樣做的一種方式是繼承ConcurrentHashMap的,如下面的例子:

class ConcurrentHashMapWithEvent<K, V> extends ConcurrentHashMap<K, V> { 
    ... 
    @Override public V put(K key, V value) { 
    System.out.println("This is right before put(" + k + ", " + v + ")"); 
    super.put(k, v); 
    System.out.println("This is right after put(" + k + ", " + v + ")"); 
    } 
    ... 
    public void registerCallback(EventCondition cond, Callback callback) { ... } 
} 

相反的println,你將有一些邏輯,以檢查是否kv,地圖或任何狀態,符合一定的EventCondition,並啓動相應的回調。

這種模式,即攔截方法調用執行一些代碼之前和一些代碼之後,被稱爲Aspect Oriented Programming

+0

是的,謝謝。問題在於,在put或remove之後迭代已註冊的監聽器時,如果沒有上下文切換能夠在put/remove和監聽器的調用之間進入,否則,你可能會遇到這樣的情況,聽衆的請求與放入/移除操作不符合時間,例如,偵聽器被調用的順序並不反映放置/刪除操作的順序。因此,put/remove和listener調用必須位於一個同步塊降級併發中。 – OlliP