Tengo una ArrayList que quiero usar para contener objetos RaceCar que extienden la clase Thread tan pronto como terminan de ejecutarse. Una clase, llamada Race, maneja esta ArrayList usando un método de devolución de llamada que el objeto RaceCar llama cuando termina de ejecutarse. El método de devolución de llamada, addFinisher (RaceCar finisher), agrega el objeto RaceCar a ArrayList. Se supone que esto da el orden en que los subprocesos terminan de ejecutarse.
Sé que ArrayList no está sincronizado y, por lo tanto, no es seguro para subprocesos. Intenté usar el método Collections.synchronizedCollection (c Collection) pasando una nueva ArrayList y asignando la colección devuelta a una ArrayList. Sin embargo, esto me da un error de compilación:
Race.java:41: incompatible types
found : java.util.Collection
required: java.util.ArrayList
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));
Aquí está el código relevante:
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);
}
Lo que necesito saber es, ¿estoy usando un enfoque correcto y, de no ser así, qué debo usar para que mi código sea seguro para subprocesos? ¡Gracias por la ayuda!
List
interfaz no es lo suficientemente completa para ser muy útil en múltiples hilos.)Collections.synchronizedList()
, tendríamos una condición de carrera REAL aquí: PRespuestas:
Utilice
Collections.synchronizedList()
.Ex:
Collections.synchronizedList(new ArrayList<YourClassNameHere>())
fuente
Cambio
private ArrayList finishingOrder; //Make an ArrayList to hold RaceCar objects to determine winners finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars)
a
private List finishingOrder; //Make an ArrayList to hold RaceCar objects to determine winners finishingOrder = Collections.synchronizedList(new ArrayList(numberOfRaceCars)
List es un supertipo de ArrayList, por lo que debe especificarlo.
De lo contrario, lo que estás haciendo parece estar bien. Otra opción es que puede usar Vector, que está sincronizado, pero esto es probablemente lo que haría yo.
fuente
List
probablemente sería más útil. OList<RaceCar>
.//Print out winner System.out.println("The Winner is " + ((RaceCar) finishingOrder.get(0)).toString() + "!");
dice que no se encuentra el método get (0). PensamientosCopyOnWriteArrayList
Usa
CopyOnWriteArrayList
clase. Esta es la versión segura para subprocesos deArrayList
.fuente
ConcurrentLinkedQueue
Es posible que esté utilizando el enfoque incorrecto. El hecho de que un hilo que simula un coche termine antes que otro hilo de simulación de coche no significa que el primer hilo deba ganar la carrera simulada.
Depende mucho de tu aplicación, pero podría ser mejor tener un hilo que calcule el estado de todos los autos en pequeños intervalos de tiempo hasta que se complete la carrera. O, si prefiere utilizar varios hilos, puede hacer que cada automóvil registre el tiempo "simulado" que tardó en completar la carrera y elegir al ganador como el que tiene el menor tiempo.
fuente
También puede usar la
synchronized
palabra clave para unaddFinisher
método como este//Implement the one method in the RaceListener interface public synchronized void addFinisher(RaceCar finisher) { finishingOrder.add(finisher); }
Por lo tanto, puede usar ArrayList agregar método seguro para subprocesos de esta manera.
fuente
final Object
lugar cada vez que accedaCollection
a él de cualquier manera.Siempre que desee utilizar una versión segura para subprocesos ant del objeto de colección ant, utilice la ayuda del paquete java.util.concurrent. * . Tiene casi todas las versiones simultáneas de objetos de colección no sincronizados. por ejemplo: para ArrayList, tiene java.util.concurrent.CopyOnWriteArrayList
Puede hacer Collections.synchronizedCollection (cualquier objeto de colección), pero recuerde este sincronizador clásico. La técnica es cara y viene con gastos generales de ejecución. El paquete java.util.concurrent. * es menos costoso y administra el rendimiento de una mejor manera mediante el uso de mecanismos como
Por lo tanto, prefiera algo del paquete java.util.concurrent. *
fuente
En su lugar, también puede usar como Vector, ya que los vectores son seguros para subprocesos y la lista de matrices no. Aunque los vectores son antiguos, pueden resolver su propósito fácilmente.
Pero puede hacer que su Arraylist esté sincronizada como un código dado esto:
Collections.synchronizedList(new ArrayList(numberOfRaceCars()));
fuente
Puede cambiar de tipo ArrayList a Vector, en el que todos los métodos están sincronizados.
private Vector finishingOrder; //Make a Vector to hold RaceCar objects to determine winners finishingOrder = new Vector(numberOfRaceCars);
fuente