Question

Je ne sais pas si c'est le bon moyen de synchroniser mon ArrayList .

J'ai une ArrayList in_queue qui est transmise à partir de la fonction registerInQueue .

ArrayList<Record> in_queue = null;

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

Maintenant, j'essaie de le synchroniser. Ceci synchronise-t-il correctement mon objet 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);
    }
}
Était-ce utile?

La solution

Vous synchronisez deux fois, ce qui est inutile et peut éventuellement ralentir le code: les modifications effectuées lors de l'itération sur la liste nécessitent une synchronisation pour l'ensemble de l'opération, ce que vous effectuez avec synchronized (in_queue_list) Collections.synchronizedList () est superflu dans ce cas (il crée un wrapper qui synchronise les opérations individuelles).

Cependant, puisque vous videz complètement la liste, la suppression itérée du premier élément est la pire des manières de le faire. En effet, pour chaque élément, tous les éléments suivants doivent être copiés, ce qui en fait un O (n ^ 2) opération - horriblement lent pour les grandes listes.

Au lieu de cela, appelez simplement clear () - aucune itération requise.

Modifier: Si vous avez besoin de la synchronisation à une seule méthode de Collections.synchronizedList () ultérieurement, cette méthode est la bonne:

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

Mais dans de nombreux cas, la synchronisation avec une seule méthode est insuffisante (par exemple, pour toutes les itérations ou lorsque vous obtenez une valeur, effectuez des calculs basés sur celle-ci et remplacez-la par le résultat). Dans ce cas, vous devez quand même utiliser la synchronisation manuelle. Collections.synchronizedList () est donc une surcharge inutile.

Autres conseils

En regardant votre exemple, je pense ArrayBlockingQueue (ou ses frères et sœurs) peut être utile. Ils se chargent de la synchronisation pour vous, afin que les threads puissent écrire dans la file d'attente ou jeter un coup d'œil / prendre sans effectuer de travail de synchronisation supplémentaire.

C'est correct et documenté:

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

Toutefois, pour effacer la liste, appelez simplement List.clear () .

Oui, c'est la bonne façon, mais le bloc synchronisé est requis si vous voulez que tous les retraits soient sécurisés ensemble - à moins que la file d'attente ne soit vide, aucun retrait n'est autorisé. J'imagine que vous souhaitez simplement que les opérations de file d'attente et de retrait de la file d'attente soient sécurisées afin de pouvoir supprimer le bloc synchronisé.

Cependant, il existe beaucoup de files d'attente concurrentes très avancées en Java, telles que ConcurrentLinkedQueue

Prenons une liste normale (implémentée par la classe ArrayList) et synchronisons-la. Ceci est montré dans la classe SynchronizedListExample.     Nous passons à la méthode Collections.synchronizedList une nouvelle ArrayList of Strings. La méthode retourne une liste de chaînes synchronisée.     // Voici 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());
            }
        }    
    }
}

Notez que lors de l'itération dans la liste, cet accès est toujours effectué à l'aide d'un bloc synchronisé qui se verrouille sur l'objet synchronizedList. En général, les itérations sur une collection synchronisée doivent être effectuées dans un bloc synchronisé

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top