Высокопроизводительный параллельный MultiMap Java / Scala - PullRequest
57 голосов
/ 03 сентября 2010

Я ищу высокопроизводительную параллельную MultiMap. Я искал везде, но я просто не могу найти решение, которое использует тот же подход, что и ConcurrentHashMap (только блокировка сегмента хеш-массива).

Мультикарта будет часто читаться, добавляться и удаляться.

Ключ мультикарты будет строкой, а его значение будет произвольным.

Мне нужно O (1), чтобы найти все значения для данного ключа, O (N) в порядке для удаления, но O (logN) предпочтительнее.

Крайне важно, чтобы удаление последнего значения для данного ключа удаляло контейнер значений из ключа, чтобы не допустить утечки памяти.

ЗДЕСЬ РЕШЕНИЕ, которое Я СОСТАВИЛ, доступно в ApacheV2: Индекс (мультикарта)

Ответы [ 9 ]

12 голосов
/ 03 сентября 2010

Почему бы не обернуть ConcurrentHashMap [T, ConcurrentLinkedQueue [U]] некоторыми хорошими скала-подобными методами (например, неявное преобразование в Iterable или все, что вам нужно, и метод обновления)?

8 голосов
/ 03 сентября 2010

Вы пробовали Коллекции Google?Они имеют различные реализации Multimap .

4 голосов
/ 17 июня 2013

В акке есть один , хотя я не использовал его.

3 голосов
/ 11 июля 2013

Я сделал микшин ConcurrentMultiMap , который расширяет миксины mutable.MultiMap и имеет собственный тип concurrent.Map [A, Set [B]].Он блокируется по ключу, что имеет O (n) пространственную сложность, но его временная сложность довольно хорошая, если вы не особенно требовательны к записи.

1 голос
/ 12 сентября 2012

У меня было требование, при котором я должен был иметь Map<Comparable, Set<Comparable>>, где вставка на карту должна выполняться одновременно, а также в соответствующем наборе, но как только ключ был использован на карте, его пришлось удалить, подумайте, если это как Работа, выполняемая каждые две секунды, которая потребляет целое Set<Comparable> от определенного ключа, но вставка должна быть полностью параллельной, так что большинство значений буферизуется при запуске задания, вот моя реализация:

Примечание: Я использую класс помощника Guava Maps для создания одновременных карт, также это решение эмулирует Параллелизм Java на практике Листинг 5.19 :

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

}
1 голос
/ 22 ноября 2011

Вы должны попробовать ctries . вот это pdf .

0 голосов
/ 31 мая 2017

Я немного опоздал на эту тему, но я думаю, что в настоящее время вы можете использовать Guava следующим образом:

Multimaps.newSetMultimap(new ConcurrentHashMap<>(), ConcurrentHashMap::newKeySet)
0 голосов
/ 22 ноября 2011

Уже поздно для обсуждения ...

Когда речь идет о высокопроизводительных параллельных вещах, нужно быть готовым к написанию решения.С Concurrent утверждение Дьявол в деталях имеет полное значение.Возможно реализовать структуру полностью одновременно и без блокировки.

Начальной базой будет NonBlocking Hashtable http://sourceforge.net/projects/high-scale-lib/, а затем в зависимости от того, сколько значений на ключ и как часто нужно добавлять / удалять некоторые копии при записи Object [] для значений или на основе массива. Set withсемафор / спин-блокировка.

0 голосов
/ 03 сентября 2010

Вы посмотрели на Javalution , который предназначен для реального времени и т. Д. И, конечно, высокой производительности.

...