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.concurrentpakiecie 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.concurrentpakiecie jest najlepsza w tym przypadku?
ConcurrentModificationExceptionMoż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.concurrentto 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 Queues i Maps (i można utworzyć Sets z Maps), 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ć:
CopyOnWriteArrayListma 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());
ConcurrentHashMapchociaż Collections.synchronizedMapmetoda.
ConcurrentHashMap. Szczegóły implementacji synchronizacji są różne. używanie tych synchronizedmetod w Collectionszasadzie po prostu opakowuje klasę w monitorze Java. ConcurrentHashMapwykorzystuje 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.
ConcurrentLinkedQueueużywa kolejki bez blokady (opartej na nowszej instrukcji CAS ).
Listinterfejsu.
List.set(int index, Object element)z ConcurrentLinkedQueue?
Listmetod 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 Queuejest 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.