J'ai une ArrayList que je veux utiliser pour contenir des 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 une fois son exécution terminée. La méthode de rappel, addFinisher (finisseur RaceCar), ajoute l'objet RaceCar à ArrayList. Ceci est censé donner l'ordre dans lequel les threads finissent de s'exécuter.
Je sais que 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 passant une nouvelle ArrayList et en attribuant la collection retournée à une 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 j'ai besoin de 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!
List
interface n'est pas vraiment assez complète pour être très utile en multithreading.)Collections.synchronizedList()
, nous aurions une VRAIE condition de course ici: PRéponses:
Utilisez
Collections.synchronizedList()
.Ex:
la source
Changement
à
List est un supertype de ArrayList, vous devez donc le spécifier.
Sinon, ce que vous faites semble bien. Une autre option est que vous pouvez utiliser Vector, qui est synchronisé, mais c'est probablement ce que je ferais.
la source
List
serait probablement plus utile. OuList<RaceCar>
.//Print out winner System.out.println("The Winner is " + ((RaceCar) finishingOrder.get(0)).toString() + "!");
il dit que la méthode get (0) n'est pas trouvée. Pensées?CopyOnWriteArrayList
Utilisez la
CopyOnWriteArrayList
classe. Il s'agit de la version thread-safe deArrayList
.la source
ConcurrentLinkedQueue
Vous utilisez peut- être la mauvaise approche. Ce n'est pas parce qu'un thread qui simule une voiture se termine avant un autre thread de simulation de voiture que le premier thread devrait gagner la course simulée.
Cela dépend beaucoup de votre application, mais il serait peut-être préférable d'avoir un thread qui calcule l'état de toutes les voitures à de petits intervalles de temps jusqu'à ce que la course soit terminée. Ou, si vous préférez utiliser plusieurs threads, vous pouvez demander à chaque voiture d'enregistrer le temps «simulé» nécessaire pour terminer la course et de choisir le vainqueur comme celui avec le temps le plus court.
la source
Vous pouvez également utiliser un
synchronized
mot-clé pour uneaddFinisher
méthode comme celle-ciVous pouvez donc utiliser ArrayList add méthode thread-safe de cette manière.
la source
final Object
place chaque fois que vous accédez auCollection
de quelque manière que ce soit.Chaque fois que vous souhaitez utiliser la version ant thread-safe de la collection ant, prenez l'aide du package java.util.concurrent. * . Il a presque toutes les versions simultanées des 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 ce synchr classique. La technique est coûteuse et s'accompagne de frais généraux de performance. Le package java.util.concurrent. * est moins cher et gère mieux les performances en utilisant des mécanismes tels que
Alors, préférez quelque chose du package java.util.concurrent. *
la source
Vous pouvez également utiliser comme vecteur à la place, car les vecteurs sont thread-safe et les arraylist ne le sont pas. Bien que les vecteurs soient anciens, ils peuvent facilement résoudre votre objectif.
Mais vous pouvez synchroniser votre Arraylist comme du code étant donné ceci:
la source
Vous pouvez passer du type ArrayList au type Vector, dans lequel chaque méthode est synchronisée.
la source