Ich habe das Problem des Schreibens einer gleichzeitigen Multimap untersucht, und ich habe eine Implementierung durch die Google Guava AbstractSetMultimap und eine MapMaker Computing-Karte, die bei Bedarf erstellt die Werte-Sammlungen als eine Reihe Ansicht über eine ConcurrentHashMap. Mit ein wenig Sorgfalt über die View-Sammlungen und verschiedene Wrapper denke ich, dass das ziemlich nah ist.Implementierung entfernen auf einer ConcurrentMultimap ohne Rennen
Das große Problem, das bereits discussed von others war die have dies versuchten, den Anschein, dass die Entfernung die Werte-Sammlungen aus der zugrunde liegenden Karte sein, wenn sie leer werden, ohne Rennbedingungen einzuführen.
Ein paar Optionen scheinen zu existieren.
- die leeren Sammlungen dort lassen. Dies wird einige CHMs verlieren, aber ich glaube, dass es zumindest korrekt ist.
- versuchen Sie optimistisch, die Sammlung zu entfernen, wenn sie leer ist, und kompensieren Sie, wenn etwas anderes darin erscheint. Dies ist voller Rassen und scheint unmöglich zu beheben.
- synchronisieren Sie alles auf der Werte-Sammlung, die zumindest diese Entfernung erlauben würde, aber auf Kosten von Nebenläufigkeit nach der anfänglichen Suche nach Schlüssel.
- für eine kleinere Strafe (vielleicht abhängig von Nutzungsmuster?), Vielleicht synchronisieren auf Werte-Sammlung erstellen und entfernen, müssen überprüfen, ob das alles abdeckt.
Fragen:
- jemand eine bessere Umsetzung als dies weiß es? Können wir besser Teile von MapMaker zusammensetzen, oder braucht es eine spezielle ConcurrentHashMultimap, die von Grund auf neu geschrieben wurde?
- Wenn es schwierig ist, viel zu verbessern, ist dieses Leck in der Praxis wahrscheinlich ein großes Problem? Bemerkenswerte Auflistungen wie java.util.HashMap, juc.ConcurrentHashMap und ArrayDeque ändern die Größe des Sicherungsspeichers nicht nach unten, und ArrayList führt dies nicht automatisch aus. Solange wir die Objekte ausräumen, frage ich mich, ob das zu wichtig ist.
Dank
Edit: siehe auch the discussion here auf der Guave-Mailingliste.
Edit 2: Ich habe dies seit geschrieben. Eine Implementierung finden Sie unter this Google code area. Ich würde jedes Feedback von jedem, der es versucht, sehr begrüßen, eher dort als hier.
Die Art und Weise, wie ich das Live-View-Verhalten löste, war, dass 'multimap.get ("foo") 'ein' ForwardingSet' zurückgibt, das an das echte delegiert. Daher sucht jede Operation in diesem Satz den Unterschlüssel nach, der zwischen zwei beliebigen Aufrufen wechseln kann. Diese Indirektion behandelt die meisten Probleme dort, denke ich, aber verursacht eine unechte Werte-Sammlung, die bei jeder Operation auf einem nicht vorhandenen Schlüssel erstellt wird. Danke für Ihre Kommentare. –