Scegliere il miglior elenco di concorrenza in Java [chiuso]


98

Il mio pool di thread ha un numero fisso di thread. Questi thread devono scrivere e leggere frequentemente da un elenco condiviso.

Quindi, quale struttura dati (meglio essere una lista, deve essere senza monitor) nel java.util.concurrentpacchetto è la migliore in questo caso?


5
Dipende da cosa vuoi fare con la collezione. Vedi il mio post sul blog (sebbene si tratti di .Net, i concetti sono gli stessi). È improbabile che tu possa scrivere codice thread-safe corretto con un file List.
SLaks

1
Ora, sto usando CopyOnWriteArrayList , ma l' eccezione ConcurrentModificationException viene ancora generata occasionalmente.
象 嘉 道

2
Includi maggiori informazioni su ciò che stai facendo con la raccolta in modo che le persone possano rispondere meglio, altrimenti è solo una supposizione.
mattsh

2
Il ConcurrentModificationExceptionnon potrebbe provenire da un problema di sincronizzazione; ad esempio, si verifica anche in un ciclo for su una raccolta in cui si tenta di rimuovere un elemento dalla raccolta.
toto2

1
So che non fa parte del pacchetto, ma qualcuno ha provato Vector?
WesternGun

Risposte:


96

è meglio che sia List

L' unica List implementazione in java.util.concurrentè CopyOnWriteArrayList . C'è anche l'opzione di un elenco sincronizzato come menziona Travis Webb.

Detto questo, sei sicuro di aver bisogno che sia un List? Ci sono molte più opzioni per concomitanti Queues e Maps (e si può fare Sets da Maps), e quelle strutture tendono a rendere più senso per molti dei tipi di cose che vuoi fare con una struttura dati condivisa.

Per le code, hai un numero enorme di opzioni e quale è più appropriata dipende da come devi usarla:


14
CopyOnWriteArrayListha lo svantaggio di essere molto costoso in scrittura (ma economico in lettura) Se stai facendo molte scritture, è meglio che tu abbia una Lista sincronizzata o una coda.
Peter Lawrey

67

Qualsiasi raccolta Java può essere resa thread-safe in questo modo:

List newList = Collections.synchronizedList(oldList);

O per creare un nuovo elenco thread-safe:

List newList = Collections.synchronizedList(new ArrayList());

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)


7
Per questo motivo, non troverai implementazioni di elenchi in java.util.concurrent - Uhm, esiste ConcurrentHashMapanche se esiste un Collections.synchronizedMapmetodo.
aioobe

7
Leggi i Javadoc ConcurrentHashMap. I dettagli dell'implementazione della sincronizzazione sono diversi. l'utilizzo dei synchronizedmetodi in Collectionspratica avvolge semplicemente la classe in un monitor Java. ConcurrentHashMaputilizza funzionalità di concorrenza più intelligenti.
Travis Webb

1
Sì. Tuttavia, rende la tua ultima frase in qualche modo non valida.
aioobe

1
Se usi un monitor, le prestazioni del programma sono davvero pessime :-(
象 嘉 道

5
Solo per aggiungere, l'iterazione su newList non è thread-safe. !!
bluelurker

9

Se la dimensione dell'elenco è fissa, è possibile utilizzare AtomicReferenceArray . Ciò consentirebbe di eseguire aggiornamenti indicizzati a uno slot. È possibile scrivere una visualizzazione elenco, se necessario.


6

Potresti dare un'occhiata a ConcurrentDoublyLinkedList scritto da Doug Lea basato su "A Practical Lock-Free Double-Linked List" di Paul Martin. Non implementa l'interfaccia java.util.List, ma offre la maggior parte dei metodi che useresti in un elenco.

Secondo il javadoc:

Un'implementazione simultanea di un elenco collegato di una Deque (coda a doppia estremità). Le operazioni simultanee di inserimento, rimozione e accesso vengono eseguite in modo sicuro su più thread. Gli iteratori sono debolmente coerenti e restituiscono elementi che riflettono lo stato del deque a un certo punto o dopo la creazione dell'iteratore. Essi non gettano ConcurrentModificationException, e può procedere in concomitanza con altre operazioni.


5

ConcurrentLinkedQueueutilizza una coda priva di blocchi (basata sulla nuova istruzione CAS ).


7
... che non implementa l' Listinterfaccia.
aioobe

1
eSniff, come implementeresti List.set(int index, Object element)con ConcurrentLinkedQueue?
John Vint

4
La maggior parte dei Listmetodi -specific non saranno implementabili usando a Queue(add / set at a specific index, for example) o possono essere implementati ma saranno inefficienti (ottenere da un indice). Quindi non penso che potresti davvero avvolgerlo. Detto questo, penso che il suggerimento di a Queuevada bene poiché l'OP non ha realmente spiegato perché hanno bisogno di un file List.
ColinD

1
@ColinD questa è la risposta che stavo cercando. Ci sono buone ragioni per cui il CLQ non può essere racchiuso in una lista. Sebbene sia d'accordo, non posso escludere l'interfaccia della coda.
John Vint

1
❗️ Vale la pena notare che: "Attenzione che, a differenza della maggior parte delle raccolte, il metodo delle dimensioni NON è un'operazione a tempo costante. A causa della natura asincrona di queste code, la determinazione del numero corrente di elementi richiede un attraversamento degli elementi."
Behrang Saeedzadeh

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.