Domanda

Non sono sicuro che questo sia il modo corretto di sincronizzare il mio ArrayList .

Ho un ArrayList in_queue che viene passato dalla funzione registerInQueue .

ArrayList<Record> in_queue = null;

public void registerInQueue(ArrayList in_queue)
{
    this.in_queue = in_queue;
}

Ora sto provando a sincronizzarlo. Questo sta sincronizzando correttamente il mio oggetto in_queue ?

List<Record> in_queue_list = Collections.synchronizedList(in_queue);

synchronized (in_queue_list) {
    while (in_queue_list.size() > 0) {
        in_queue_list.remove(0);
    }
}
È stato utile?

Soluzione

Stai sincronizzando due volte, il che è inutile e forse rallenta il codice: le modifiche durante l'iterazione sull'elenco richiedono una sincronizzazione sull'intera operazione, che stai facendo con sincronizzato (in_queue_list) Collections.synchronizedList () è superfluo in quel caso (crea un wrapper che sincronizza le singole operazioni).

Tuttavia, poiché stai svuotando completamente l'elenco, la rimozione ripetuta del primo elemento è il modo peggiore per farlo, per ogni elemento bisogna copiare tutti gli elementi seguenti, rendendolo O (n ^ 2) operazione - orribilmente lenta per elenchi più grandi.

Invece, chiama semplicemente clear () - nessuna iterazione necessaria.

Modifica Se hai bisogno della sincronizzazione a metodo singolo di Collections.synchronizedList () in seguito, questo è il modo corretto:

List<Record> in_queue_list = Collections.synchronizedList(in_queue);
in_queue_list.clear(); // synchronized implicitly, 

Ma in molti casi, la sincronizzazione a metodo singolo è insufficiente (ad esempio per tutte le iterazioni o quando si ottiene un valore, eseguire calcoli basati su di esso e sostituirlo con il risultato). In tal caso, devi comunque utilizzare la sincronizzazione manuale, quindi Collections.synchronizedList () è solo un sovraccarico aggiuntivo inutile.

Altri suggerimenti

Guardando il tuo esempio, penso ArrayBlockingQueue (o suoi fratelli) possono essere utili. Si occupano della sincronizzazione per te, quindi i thread possono scrivere in coda o sbirciare / prendere senza ulteriore lavoro di sincronizzazione da parte tua.

È corretto e documentato:

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

Tuttavia, per cancellare l'elenco, basta chiamare List.clear () .

Sì, è il modo corretto, ma è necessario il blocco sincronizzato se si desidera che tutte le rimozioni siano sicure, a meno che la coda non sia vuota, non sono consentite rimozioni. Suppongo che tu voglia solo operazioni di coda e di dequeue sicure, in modo da poter rimuovere il blocco sincronizzato.

Tuttavia, ci sono code simultanee molto avanzate in Java come ConcurrentLinkedQueue

Prendiamo un normale elenco (implementato dalla classe ArrayList) e rendiamolo sincronizzato. Questo è mostrato nella classe SynchronizedListExample.     Passiamo al metodo Collections.synchronizedList un nuovo ArrayList of Strings. Il metodo restituisce un Elenco di stringhe sincronizzato.     // Ecco la classe SynchronizedArrayList

package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
/**
* 
* @author manoj.kumar
* @email kumarmanoj.mtech@gmail.com
* 
*/
public class SynchronizedArrayList {
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());
    public static void main(String[] args) {    
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>());
        synchronizedList.add("Aditya");
        synchronizedList.add("Siddharth");
        synchronizedList.add("Manoj");
        // when iterating over a synchronized list, we need to synchronize access to the synchronized list
        synchronized (synchronizedList) {
            Iterator<String> iterator = synchronizedList.iterator();
            while (iterator.hasNext()) {
                log.info("Synchronized Array List Items: " + iterator.next());
            }
        }    
    }
}

Si noti che quando si scorre ripetutamente l'elenco, questo accesso viene comunque eseguito utilizzando un blocco sincronizzato che si blocca sull'oggetto synchronizedList. In generale, l'iterazione su una raccolta sincronizzata dovrebbe essere eseguita in un blocco sincronizzato

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top