Moja pula wątków ma stałą liczbę wątków. Wątki te muszą często pisać i czytać z udostępnionej listy.
Jaka więc struktura danych (lepiej lista, musi być wolna od monitora) w java.util.concurrent
pakiecie jest najlepsza w tym przypadku?
Moja pula wątków ma stałą liczbę wątków. Wątki te muszą często pisać i czytać z udostępnionej listy.
Jaka więc struktura danych (lepiej lista, musi być wolna od monitora) w java.util.concurrent
pakiecie jest najlepsza w tym przypadku?
ConcurrentModificationException
Może nie pochodzić z problemem synchronizacji; pojawia się również na przykład w pętli for nad kolekcją, w której próbujesz usunąć element z kolekcji.
Vector
?
Odpowiedzi:
lepiej by było
List
Tylko List
realizacja w java.util.concurrent
to CopyOnWriteArrayList . Istnieje również opcja zsynchronizowanej listy, o której wspomina Travis Webb.
To powiedziawszy, czy na pewno potrzebujesz, aby to był List
? Istnieje o wiele więcej opcji dla współbieżnych Queue
s i Map
s (i można utworzyć Set
s z Map
s), a te struktury mają zwykle największy sens w przypadku wielu rodzajów rzeczy, które chcesz zrobić ze wspólną strukturą danych.
W przypadku kolejek masz ogromną liczbę opcji i to, która z nich jest najbardziej odpowiednia, zależy od tego, jak chcesz z niej skorzystać:
CopyOnWriteArrayList
ma tę wadę, że jest bardzo kosztowny przy zapisie (ale tani jak na odczyt). Jeśli robisz dużo zapisów, lepiej będzie mieć zsynchronizowaną listę lub kolejkę.
Dowolną kolekcję Java można ustawić jako bezpieczną dla wątków, na przykład:
List newList = Collections.synchronizedList(oldList);
Lub utworzyć zupełnie nową listę bezpiecznych wątków:
List newList = Collections.synchronizedList(new ArrayList());
ConcurrentHashMap
chociaż Collections.synchronizedMap
metoda.
ConcurrentHashMap
. Szczegóły implementacji synchronizacji są różne. używanie tych synchronized
metod w Collections
zasadzie po prostu opakowuje klasę w monitorze Java. ConcurrentHashMap
wykorzystuje bardziej inteligentne funkcje współbieżności.
Jeśli rozmiar listy został ustalony, możesz użyć AtomicReferenceArray . Umożliwiłoby to wykonanie indeksowanych aktualizacji slotu. W razie potrzeby możesz napisać widok listy.
Możesz spojrzeć na ConcurrentDoublyLinkedList napisaną przez Douga Leę na podstawie „Praktycznej listy podwójnie połączonej bez blokad” Paula Martina. Nie implementuje interfejsu java.util.List, ale oferuje większość metod, których można użyć na liście.
Według javadoc:
Współbieżna implementacja listy połączonej Deque (kolejka dwustronna). Jednoczesne operacje wstawiania, usuwania i uzyskiwania dostępu są bezpiecznie wykonywane w wielu wątkach. Iteratory są słabo spójne , zwracając elementy odzwierciedlające stan deque w pewnym momencie lub od chwili utworzenia iteratora. Oni nie rzucać ConcurrentModificationException i może postępować równolegle z innymi operacjami.
ConcurrentLinkedQueue
używa kolejki bez blokady (opartej na nowszej instrukcji CAS ).
List
interfejsu.
List.set(int index, Object element)
z ConcurrentLinkedQueue?
List
metod specyficznych albo nie będzie możliwa do zaimplementowania przy użyciu Queue
(na przykład dodawania / ustawiania w określonym indeksie) lub może zostać zaimplementowana, ale będzie nieefektywna (pobierz z indeksu). Więc nie sądzę, żebyś naprawdę mógł to opakować. To powiedziawszy, myślę, że sugestia a Queue
jest w porządku, ponieważ OP tak naprawdę nie wyjaśnił, dlaczego potrzebują List
.
Jeśli set jest wystarczający, można użyć ConcurrentSkipListSet . (Jego implementacja jest oparta na ConcurrentSkipListMap, która implementuje listę pominięć ).
Oczekiwany średni koszt czasu to log (n) dla operacji zawierania, dodawania i usuwania; metoda rozmiaru nie jest operacją działającą w czasie stałym.
List
.