簡體   English   中英

高性能並發 MultiMap Java/Scala

[英]High-performance Concurrent MultiMap Java/Scala

我正在尋找高性能、並發的 MultiMap。 我到處搜索,但我根本找不到使用與 ConcurrentHashMap 相同方法的解決方案(僅鎖定哈希數組的一部分)。

多圖將經常被讀取、添加和刪除。

multimap 鍵將是一個字符串,它的值將是任意的。

我需要 O(1) 來查找給定鍵的所有值,O(N) 可以刪除,但 O(logN) 將是首選。

刪除給定鍵的最后一個值會從鍵中刪除值的容器,以免泄漏內存,這一點至關重要。

編輯:這是我構建的解決方案,在 ApacheV2 下可用: 索引(多圖)

為什么不用一些漂亮的 Scala 式方法(例如隱式轉換為 Iterable 或任何您需要的方法,以及更新方法)來包裝 ConcurrentHashMap[T,ConcurrentLinkedQueue[U]] ?

你試過谷歌收藏嗎? 他們有各種Multimap實現。

akka 里一個,雖然我沒用過。

我做了一個ConcurrentMultiMap mixin,它擴展了 mutable.MultiMap mixin 並有一個 concurrent.Map[A, Set[B]] 自我類型。 它按鍵鎖定,具有 O(n) 空間復雜度,但如果您不是特別需要大量寫入,它的時間復雜度非常好。

我有一個要求,我必須有一個Map<Comparable, Set<Comparable>> ,其中在 Map 上的插入是並發的,也在相應的 Set 上,但是一旦從 Map 中消耗了一個 Key,就必須將其刪除,想想如果作為每兩秒運行一次的作業,它消耗來自特定鍵的整個Set<Comparable>但插入是完全並發的,以便在作業啟動時緩沖大多數值,這是我的實現:

注意:我使用 Guava 的輔助類 Maps 來創建並發映射,而且,這個解決方案模擬了實踐清單 5.19 中的 Java 並發

import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

/**
 * A general purpose Multimap implementation for delayed processing and concurrent insertion/deletes.
 *
 * @param <K> A comparable Key
 * @param <V> A comparable Value
 */
public class ConcurrentMultiMap<K extends Comparable, V extends Comparable>
{
  private final int size;
  private final ConcurrentMap<K, Set<V>> cache;
  private final ConcurrentMap<K, Object> locks;

  public ConcurrentMultiMap()
  {
    this(32, 2);
  }

  public ConcurrentMultiMap(final int concurrencyLevel)
  {
    this(concurrencyLevel, 2);
  }

  public ConcurrentMultiMap(final int concurrencyLevel, final int factor)
  {
    size=concurrencyLevel * factor;
    cache=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(concurrencyLevel).makeMap();
    locks=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(concurrencyLevel).weakKeys().weakValues().makeMap();
  }

  private Object getLock(final K key){
    final Object object=new Object();
    Object lock=locks.putIfAbsent(key, object);
    if(lock == null){
      lock=object;
    }
    return lock;
  }

  public void put(final K key, final V value)
  {
    synchronized(getLock(key)){
      Set<V> set=cache.get(key);
      if(set == null){
        set=Sets.newHashSetWithExpectedSize(size);
        cache.put(key, set);
      }
      set.add(value);
    }
  }

  public void putAll(final K key, final Collection<V> values)
  {
    synchronized(getLock(key)){
      Set<V> set=cache.get(key);
      if(set == null){
        set=Sets.newHashSetWithExpectedSize(size);
        cache.put(key, set);
      }
      set.addAll(values);
    }
  }

  public Set<V> remove(final K key)
  {
    synchronized(getLock(key)){
      return cache.remove(key);
    }
  }

  public Set<K> getKeySet()
  {
    return cache.keySet();
  }

  public int size()
  {
    return cache.size();
  }

}

你應該試試ctry 這是pdf

我在這個話題上有點晚了,但我認為,現在,你可以像這樣使用番石榴:

Multimaps.newSetMultimap(new ConcurrentHashMap<>(), ConcurrentHashMap::newKeySet)

使用 Gauava 的 MultiMaps。 Multimaps.synchronizedMultimap(HashMultimap.create())

討論已經晚了,但......

當涉及到高性能並發的東西時,應該准備好編寫解決方案。 與 Concurrent 中的魔鬼在細節中的陳述具有完整的含義。 可以實現完全並發和無鎖的結構。

起始基礎將是 NonBlocking Hashtable http://sourceforge.net/projects/high-scale-lib/ ,然后取決於每個鍵有多少個值以及需要在寫入 Object[] 時為值添加/刪除一些副本的頻率或帶有信號量/自旋鎖的基於數組的集合。

您是否看過用於實時等的Javalution ,當然還有高性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM