2014-02-06 63 views
4

我正在編寫一個Web服務,嚴重依賴於每小時完全更新一次的單個大型地圖。剩下的時間很多線程同時讀取表格。併發只讀HashMap

我的問題是:什麼是實現這樣一個Map最有效的構造?

該地圖可能更大(100 - 500 MB)。除了整個地圖被替換一小時之外,只有讀取權限。

我正在考慮只使用Java HashMap,也許使用反射設置更新之間的字段最終如果這可以提高性能,但我不知道如何使JVM優化許多併發讀取。

+2

訪問可以通過'ReadWriteLock'從外部管理。除此之外,你是否打算使它比「正常」的HashMap更有效率? – Marco13

+4

你有沒有證據表明正常的HashMap是不夠的? –

+0

我最害怕的是每個線程都有自己的副本。另外我讀了ConcurrentHashMap對於併發寫入的優點。 – xgb84j

回答

14

由於地圖在使用時未更新,請使用HashMap,這可以提供出色的O(1)查找性能(犧牲線程安全性)。

當需要刷新時,建立一個新的映射和交換引用。

考慮使用AtomicReference使交換線程安全:

private final AtomicReference<Map<K, V>> mapRef = new AtomicReference<>(); 

要使用:

mapRef.get().get(key); 

初始化或換一個新的地圖:

Map<K, V> newMap = new HashMap<>(); 
// populate map 
mapRef.set(newMap); // all threads will see this change 
+0

謝謝,這也是我考慮過的事情!但是,你能解釋一下你使用「AtomicReference」的意思嗎? – xgb84j

2

在你在你證明Java的標準HashMap速度不夠快之前,我認爲你可能需要使用它如果在這裏停止世界,可能會造成垃圾收集,可能會造成問題。

您可以通過總是重複使用HashMap(不要每次創建一個新的地圖)並預先分配存儲在地圖中的所有對象並重復使用它們來避免此問題。

除此之外,你可以通過使用兩個HashMaps來更快地完成替換,就像@Bohemian在他的回答中所暗示的那樣。

-1

使用此。

public class Model { 
    private Map<?, ?> values; 
    private ReadWriteLock lock = new ReentrantReadWriteLock(); 

    public ? getValue(? key) { 
    lock.readLock().lock(); 
    ? rv = values.get(key); 
    lock.readLock().unlock(); 
    return rv; 
    } 

    public void update(Map<?, ?> values) { 
    lock.writeLock().lock(); 
    rv = values; 
    //OR rv.putAll(values) 
    lock.writeLock().unlock(); 
    } 
} 
1

前往ConcurrentHashMap。它允許併發讀取訪問而不影響性能。

+0

http://stackoverflow.com/questions/1378310/performance-concurrenthashmap-vs-hashmap – dierre