HashSet jest oparty na HashMap.
Jeśli spojrzymy na HashSet<E>
implementację, wszystko jest zarządzane w ramach HashMap<E,Object>
.
<E>
jest używany jako klucz HashMap
.
I wiemy, że HashMap
nie jest to bezpieczne dla wątków. Właśnie dlatego mamy ConcurrentHashMap
Javę.
Na tej podstawie jestem zdezorientowany, dlaczego nie mamy ConcurrentHashSet, który powinien być oparty na ConcurrentHashMap
?
Czy coś jeszcze mi brakuje? Muszę używać Set
w środowisku wielowątkowym.
Ponadto, jeśli chcę stworzyć własny, ConcurrentHashSet
czy mogę to osiągnąć, po prostu zastępując HashMap
go ConcurrentHashMap
i pozostawiając resztę bez zmian?
java
collections
concurrency
hashmap
hashset
Talha Ahmed Khan
źródło
źródło
ConcurrentSkipListSet
jest oparte naConcurrentSkipListMap
implementacjiConcurrentNavigableMap
iConcurrentMap
.Odpowiedzi:
Nie ma wbudowanego typu,
ConcurrentHashSet
ponieważ zawsze możesz uzyskać zestaw z mapy. Ponieważ istnieje wiele rodzajów map, używasz metody do utworzenia zestawu z danej mapy (lub klasy mapy).Przed wersją Java 8 tworzysz współbieżny zestaw skrótów wsparty współbieżną mapą skrótu, używając
Collections.newSetFromMap(map)
W Javie 8 (wskazanej przez @Matt) można uzyskać widok współbieżnego zestawu skrótów za pośrednictwem
ConcurrentHashMap.newKeySet()
. Jest to nieco prostsze niż stare,newSetFromMap
które wymagało przejścia przez pusty obiekt mapy. Ale jest specyficzny dlaConcurrentHashMap
.W każdym razie projektanci Java mogli stworzyć nowy zestaw interfejsów za każdym razem, gdy tworzony był nowy interfejs mapy, ale wzorzec ten byłby niemożliwy do narzucenia, gdy osoby trzecie utworzyły własne mapy. Lepiej jest mieć metody statyczne, które wyprowadzają nowe zbiory; takie podejście zawsze działa, nawet gdy tworzysz własne implementacje map.
źródło
ConcurrentHashMap
, stracisz korzyści, które byś uzyskałConcurrentHashMap
?newSetFromMap
Implementacja znajduje się od linii 3841 w docjar.com/html/api/java/util/Collections.java.html . To tylko opakowanie…Collections.newSetFromMap
tworzySetFromMap
. np.SetFromMap.removeAll
metoda przekazuje doKeySetView.removeAll
, który dziedziczyConcurrentHashMap$CollectionView.removeAll
. Ta metoda jest wysoce nieefektywna przy usuwaniu elementów luzem. wyobraź sobie, żeremoveAll(Collections.emptySet())
przemierza wszystkie elementyMap
bez robienia czegokolwiek. PosiadanieConcurrentHashSet
tego, które jest poprawnie wdrażane, będzie lepsze w większości przypadków.źródło
Z Guava 15 możesz także po prostu użyć:
źródło
Jak wspomniał Ray Toal, jest to tak proste, jak:
źródło
ConcurrentHashMap
.Wygląda na to, że Java zapewnia współbieżną implementację zestawu z jego ConcurrentSkipListSet . SkipList Set to tylko szczególny rodzaj zadanej realizacji. Nadal implementuje interfejsy Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet. Może to działać dla Ciebie, jeśli potrzebujesz tylko interfejsu Set.
źródło
ConcurrentSkipListSet
elementami powinny byćComparable
ConcurrentSkipListSet
chyba że chceszSortedSet
. Zwykłą operacją, taką jak dodawanie lub usuwanie, powinno być O (1) dla aHashSet
, ale O (log (n)) dla aSortedSet
.Jak wskazano przez to najlepszy sposób uzyskania współbieżności-stanie HashSet jest za pomocą
Collections.synchronizedSet()
To działało dla mnie i nie widziałem nikogo, kto by na to naprawdę wskazywał.
EDYCJA Jest to mniej wydajne niż obecnie zatwierdzone rozwiązanie, jak zauważa Eugene, ponieważ po prostu owija Twój zestaw w zsynchronizowany dekorator, podczas gdy w
ConcurrentHashMap
rzeczywistości implementuje współbieżność niskiego poziomu i może wesprzeć Twój zestaw równie dobrze. Dziękuję panu Stepanenkovowi za wyjaśnienie.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
źródło
synchronizedSet
metoda właśnie tworzy dekorator zgodnieCollection
z metodami owinięcia, które mogłyby być bezpieczny wątku przez synchronizacji cała kolekcja. AleConcurrentHashMap
jest implementowany przy użyciu algorytmów nieblokujących i synchronizacji „niskiego poziomu” bez żadnych blokad całej kolekcji. Tak więc opakowania zCollections.synchronized
... są gorsze w środowiskach wielowątkowych ze względu na wydajność.Możesz użyć guawy,
Sets.newSetFromMap(map)
aby go zdobyć. Java 6 ma również tę metodę wjava.util.Collections
źródło
źródło
Dlaczego nie użyć: CopyOnWriteArraySet z java.util.concurrent?
źródło