Jak mogę utworzyć współbieżną instancję List, w której mogę uzyskać dostęp do elementów według indeksu? Czy JDK ma jakieś klasy lub metody fabryczne, których mogę użyć?
java
list
concurrency
AlikElzin-kilaka
źródło
źródło
List
które oryginalnie mówi, że jest to wymóg, który uważa się za wandalizm. Moderator już zablokował to pytanie z powodu osób, które narzekają, że odpowiedzi nie odpowiadają na zdewastowaną wersję pytania.locked
/closed
/ poprzedni komentarzOdpowiedzi:
W pliku java.util.concurrent istnieje jednoczesna implementacja listy . W szczególności CopyOnWriteArrayList .
źródło
Jeśli nie zależy ci na dostępie opartym na indeksach i chcesz tylko właściwości listy zachowującej porządek wstawiania, możesz rozważyć java.util.concurrent.ConcurrentLinkedQueue . Ponieważ implementuje Iterable, po zakończeniu dodawania wszystkich elementów możesz zapętlać zawartość za pomocą rozszerzonej składni:
źródło
:
) nazywa się foreach: docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.htmlMożesz bardzo dobrze korzystać z kolekcji.synchronizedList (List), jeśli wszystko, czego potrzebujesz, to prosta synchronizacja wywołań:
źródło
synchronizedList
jest „zsynchronizowany”, ale nie „równoczesny”. Jednym fundamentalnym problemem jest to, że wiele operacji List - które są oparte na indeksach - same w sobie nie są atomowe i muszą być częścią większej konstrukcji wzajemnego wykluczania.Vector
jest prostsze niżCollections.synchronizedList(new ArrayList<Object>())
.Ponieważ czynność uzyskania pozycji i pobrania elementu z danej pozycji naturalnie wymaga pewnego zablokowania (nie możesz mieć listy zawierającej zmiany strukturalne między tymi dwiema operacjami).
Ideą współbieżnego zbierania jest to, że każda operacja jest atomowa i może być wykonana bez wyraźnego blokowania / synchronizacji.
Dlatego ustalenie pozycji elementu
n
z danejList
operacji atomowej nie ma zbyt dużego sensu w sytuacji, w której przewiduje się równoczesny dostęp.źródło
Masz następujące opcje:
Collections.synchronizedList()
: Można owinąć każdąList
realizacji (ArrayList
,LinkedList
lub listę 3rd-party). Dostęp do każdej metody (odczyt i zapis) będzie chroniony przy użyciusynchronized
. Podczas używaniaiterator()
lub rozszerzania pętli należy ręcznie zsynchronizować; podczas iteracji inne wątki są całkowicie blokowane nawet przed czytaniem. Możesz także zsynchronizować osobno dla każdegohasNext
inext
połączeń, ale wtedyConcurrentModificationException
jest to możliwe.CopyOnWriteArrayList
: modyfikacja jest kosztowna, ale czytanie jest bez czekania. Iteratory nigdy nie rzucająConcurrentModificationException
, zwracają migawkę listy w momencie tworzenia iteratora, nawet jeśli lista jest modyfikowana przez inny wątek podczas iteracji. Przydatne w przypadku rzadko aktualizowanych list. Operacje zbiorcze, takie jak,addAll
są preferowane w przypadku aktualizacji - tablica wewnętrzna jest kopiowana rzadziej.Vector
: bardzo podobniesynchronizedList
, ale iteracja również jest zsynchronizowana. Jednak iteratory mogą rzucaćConcurrentModificationException
, jeśli wektor jest modyfikowany przez inny wątek podczas iteracji.Inne opcje:
Collections.unmodifiableList()
: bez blokady, bezpieczny dla wątków, ale niemodyfikowalnyQueue
lubDeque
może być alternatywą, jeśli dodajesz / usuwasz tylko na końcach listy i iterujesz listę. Brak dostępu według indeksu i dodawanie / usuwanie w dowolnych miejscach. Mają wiele współbieżnych implementacji o lepszej wydajności i lepszym współbieżnym dostępie, ale wykracza to poza zakres tego pytania. Możesz także zajrzeć na JCTools , zawierają one bardziej wydajne implementacje kolejek przeznaczone dla pojedynczego konsumenta lub pojedynczego producenta.źródło
CopyOnWriteArrayList to współbieżna alternatywa dla zsynchronizowanej listy, która implementuje interfejs List i jego część pakietu java.util.concurrent oraz jego kolekcję bezpieczną dla wątków.
CopyOnWriteArrayList jest bezpieczny w razie awarii i nie zgłasza ConcurrentModificationException, gdy podstawowa CopyOnWriteArrayList jest modyfikowana podczas iteracji, użyj osobnej kopii ArrayList.
Jest to zwykle zbyt kosztowne, ponieważ tablica kopiowania obejmowała każdą operację aktualizacji, w której zostanie utworzona sklonowana kopia. CopyOnWriteArrayList to najlepszy wybór tylko w przypadku częstych operacji odczytu.
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/CopyOnWriteArrayList.html
https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
źródło