710 Stimmen

Warum es kein ConcurrentHashSet gegen ConcurrentHashMap gibt

HashSet basiert auf HashMap.

Wenn wir uns die HashSet<E> Umsetzung, alles wird unter der Leitung von HashMap<E,Object> .

<E> wird als Schlüssel von HashMap .

Und wir wissen, dass HashMap ist nicht thread-sicher. Deshalb haben wir ConcurrentHashMap in Java.

In Anbetracht dessen bin ich verwirrt, dass warum wir nicht über ein ConcurrentHashSet verfügen, das auf dem ConcurrentHashMap ?

Gibt es noch etwas, das ich übersehen habe? Ich muss Folgendes verwenden Set in einer Multithreading-Umgebung.

Wenn ich außerdem meine eigene Datenbank erstellen möchte ConcurrentHashSet kann ich das erreichen, indem ich einfach die HashMap a ConcurrentHashMap und den Rest so lassen, wie er ist?

21voto

Nirro Punkte 747

Wie von diese Der beste Weg, ein HashSet mit Gleichzeitigkeit zu erhalten, ist die Verwendung von Collections.synchronizedSet()

Set s = Collections.synchronizedSet(new HashSet(...));

Das hat bei mir funktioniert, und ich habe noch niemanden gesehen, der wirklich darauf hingewiesen hat.

EDIT Dies ist weniger effizient als die derzeit bewährte Lösung, wie Eugene hervorhebt, da es nur Ihr Set in einen synchronisierten Dekorator einwickelt, während ein ConcurrentHashMap implementiert tatsächlich Nebenläufigkeit auf niedriger Ebene und kann Ihr Set genauso gut unterstützen. Vielen Dank also an Herrn Stepanenkov, dass er das klargestellt hat.

http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-

15voto

Bozho Punkte 570413

Sie können die Guave verwenden Sets.newSetFromMap(map) um einen zu bekommen. Java 6 hat diese Methode auch in java.util.Collections

8voto

import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ConcurrentHashSet<E> extends AbstractSet<E> implements Set<E>{
   private final ConcurrentMap<E, Object> theMap;

   private static final Object dummy = new Object();

   public ConcurrentHashSet(){
      theMap = new ConcurrentHashMap<E, Object>();
   }

   @Override
   public int size() {
      return theMap.size();
   }

   @Override
   public Iterator<E> iterator(){
      return theMap.keySet().iterator();
   }

   @Override
   public boolean isEmpty(){
      return theMap.isEmpty();
   }

   @Override
   public boolean add(final E o){
      return theMap.put(o, ConcurrentHashSet.dummy) == null;
   }

   @Override
   public boolean contains(final Object o){
      return theMap.containsKey(o);
   }

   @Override
   public void clear(){
      theMap.clear();
   }

   @Override
   public boolean remove(final Object o){
      return theMap.remove(o) == ConcurrentHashSet.dummy;
   }

   public boolean addIfAbsent(final E o){
      Object obj = theMap.putIfAbsent(o, ConcurrentHashSet.dummy);
      return obj == null;
   }
}

1voto

Shendor Punkte 639

Warum nicht verwenden: CopyOnWriteArraySet aus java.util.concurrent?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X