web-dev-qa-db-fra.com

Comment rendre mon Thread-Safe ArrayList? Une autre approche du problème en Java?

J'ai une liste de tableaux que je veux utiliser pour contenir les objets RaceCar qui étendent la classe Thread dès qu'ils ont fini de s'exécuter. Une classe, appelée Race, gère cette ArrayList à l'aide d'une méthode de rappel que l'objet RaceCar appelle à la fin de son exécution. La méthode de rappel, addFinisher (finisseur RaceCar), ajoute l'objet RaceCar à la liste ArrayList. Ceci est supposé donner l'ordre dans lequel les threads ont fini de s'exécuter.

Je sais qu'ArrayList n'est pas synchronisé et n'est donc pas thread-safe. J'ai essayé d'utiliser la méthode Collections.synchronizedCollection (c Collection) en transmettant un nouvel ArrayList et en affectant la collection renvoyée à un ArrayList. Cependant, cela me donne une erreur de compilation:

Race.Java:41: incompatible types
found   : Java.util.Collection
required: Java.util.ArrayList
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));

Voici le code pertinent:

public class Race implements RaceListener {
    private Thread[] racers;
    private ArrayList finishingOrder;

    //Make an ArrayList to hold RaceCar objects to determine winners
    finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));

    //Fill array with RaceCar objects
    for(int i=0; i<numberOfRaceCars; i++) {
    racers[i] = new RaceCar(laps, inputs[i]);

        //Add this as a RaceListener to each RaceCar
        ((RaceCar) racers[i]).addRaceListener(this);
    }

    //Implement the one method in the RaceListener interface
    public void addFinisher(RaceCar finisher) {
        finishingOrder.add(finisher);
    }

Ce que je dois savoir, c'est si j'utilise une approche correcte et si non, que dois-je utiliser pour rendre mon code thread-safe? Merci pour l'aide!

78
ericso

Utilisez Collections.synchronizedList() .

Ex:

Collections.synchronizedList(new ArrayList<YourClassNameHere>())
119
Amir Afghani

Changement 

private ArrayList finishingOrder;

//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars)

à

private List finishingOrder;

//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedList(new ArrayList(numberOfRaceCars)

La liste est un supertype de ArrayList, vous devez donc le spécifier.

Sinon, ce que vous faites semble bien. Une autre option est d'utiliser Vector, qui est synchronisé, mais c'est probablement ce que je ferais.

35
Reverend Gonzo

CopyOnWriteArrayList

Utilisez CopyOnWriteArrayList class. Ceci est la version sécurisée au fil de ArrayList .

7
Singh Piyush

Vous pourriez utilisez la mauvaise approche. Ce n’est pas parce qu’un fil qui simule une voiture se termine avant un autre fil de simulation de voiture que le premier fil doit gagner la course simulée.

Cela dépend beaucoup de votre application, mais il serait peut-être préférable de disposer d'un thread qui calcule l'état de toutes les voitures à intervalles rapprochés jusqu'à la fin de la course. Ou, si vous préférez utiliser plusieurs threads, vous pouvez faire en sorte que chaque voiture enregistre le temps "simulé" qu'il a fallu pour terminer la course et choisisse le vainqueur comme celui avec le temps le plus court.

6
erickson

Vous pouvez également utiliser le mot clé synchronized pour la méthode addFinisher comme ceci

    //Implement the one method in the RaceListener interface
    public synchronized void addFinisher(RaceCar finisher) {
        finishingOrder.add(finisher);
    }

Ainsi, vous pouvez utiliser ArrayList add method thread-safe avec cette méthode.

3
erhun

Chaque fois que vous souhaitez utiliser une version ant-thread sécurisée d'un objet de collection ant, utilisez l'aide de Java.util.concurrent. * package . Elle contient presque toutes les versions simultanées d'objets de collection non synchronisés. Par exemple: pour ArrayList, vous avez Java.util.concurrent.CopyOnWriteArrayList

Vous pouvez faire Collections.synchronizedCollection (n'importe quel objet de collection), mais souvenez-vous de cette synchr classique. Cette technique est coûteuse et entraîne une surcharge de performances . Le package Java.util.concurrent. * est moins coûteux et permet de mieux gérer les performances en utilisant des mécanismes tels que 

copie sur écriture, comparaison-échange, verrouillage, itérateurs de capture instantanée, etc.

Alors, préférez quelque chose de Java.util.concurrent. * Package

Vous pouvez également utiliser comme vecteur à la place, car les vecteurs sont thread-safe et les arraylist ne sont pas . Bien que les vecteurs soient vieux, ils peuvent résoudre facilement votre objectif.

Mais vous pouvez rendre votre Arraylist synchronisé comme un code en donnant ceci:

Collections.synchronizedList(new ArrayList(numberOfRaceCars())); 
0
Naman jain

Vous pouvez passer du type ArrayList au type Vector, dans lequel chaque méthode est synchronisée. 

private Vector finishingOrder;
//Make a Vector to hold RaceCar objects to determine winners
finishingOrder = new Vector(numberOfRaceCars);
0
darlinton