Je recherche un MultiMap simultané hautes performances. J'ai cherché partout, mais je ne trouve simplement pas de solution qui utilise la même approche que ConcurrentHashMap (verrouiller uniquement un segment du tableau de hachage).
La carte multiple sera à la fois lue, ajoutée et retirée souvent.
La clé à mappage multiple sera une chaîne et sa valeur sera arbitraire.
J'ai besoin de O(1) pour trouver toutes les valeurs d'une clé donnée. O(N) peut être supprimé, mais O(logN) serait préférable .
Il est essentiel que la suppression de la dernière valeur pour une clé donnée supprime le conteneur de valeurs de la clé, afin de ne pas perdre de mémoire.
VOICI LA SOLUTION I Build, disponible sous ApacheV2: Index (carte multiple)
Pourquoi ne pas envelopper ConcurrentHashMap [T, ConcurrentLinkedQueue [U]] avec des méthodes de type Nice Scala (par exemple, une conversion implicite en Iterable ou tout ce dont vous avez besoin, et une méthode de mise à jour)?
Avez-vous essayé Google Collections? Ils ont diverses Multimap implémentations.
Il y a un en akka bien que je ne l'ait pas utilisé.
J'ai fait un ConcurrentMultiMap mixin qui étend le mixin mutable.MultiMap et a un type self concurrent.Map [A, Set [B]]. Il se verrouille par clé, ce qui a O(n) complexité d'espace, mais sa complexité temporelle est très bonne, si vous n'êtes pas particulièrement lourd en écriture.
J'avais une exigence selon laquelle je devais avoir un Map<Comparable, Set<Comparable>>
dans lequel l'insertion sur la carte devait être simultanée et également sur le jeu correspondant, mais une fois qu'une clé avait été utilisée sur la carte, elle devait être supprimée. qui consomme la totalité du Set<Comparable>
à partir d'une clé spécifique mais que l'insertion soit totalement concurrente afin que la plupart des valeurs soient mises en mémoire tampon lorsque le travail débute, voici ma mise en œuvre:
Remarque: / J'utilise la classe de cartes d'assistance de Guava pour créer les cartes simultanées. Cette solution émule également la concurrence Concurrence Java dans le listing de pratique 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();
}
}
Je suis un peu en retard sur ce sujet mais je pense qu’aujourd’hui, vous pouvez utiliser Guava comme ceci:
Multimaps.newSetMultimap(new ConcurrentHashMap<>(), ConcurrentHashMap::newKeySet)
Avez-vous jeté un œil à Javalution qui est destiné au temps réel, etc. et bien sûr à la haute performance.
Il est tard pour la discussion, pourtant ...
Lorsqu'il s'agit de solutions simultanées hautes performances, il faut être prêt à coder la solution. Avec Concurrent, la déclaration le diable est dans les détails a une signification complète. Il est possible de mettre en œuvre la structure entièrement simultanée et sans verrouillage.
La base de départ serait la table de hachage NonBlocking http://sourceforge.net/projects/high-scale-lib/ puis en fonction du nombre de valeurs par clé et de la fréquence à laquelle vous devez ajouter/supprimer une copie à l'écriture Object [] pour les valeurs ou un ensemble basé sur un tableau avec un verrou de sémaphore/spin.