Pregunta ¿Cómo puedo hacer mi ArrayList Thread-Safe? ¿Otro enfoque al problema en Java?


Tengo una ArrayList que quiero usar para contener los objetos RaceCar que extienden la clase Thread tan pronto como terminan de ejecutarse. Una clase, llamada Race, maneja este ArrayList utilizando 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 (Finalizador RaceCar), agrega el objeto RaceCar a ArrayList. Se supone que esto da el orden en que los hilos terminan de ejecutarse.

Sé que ArrayList no está sincronizado y, por lo tanto, no es seguro para subprocesos. Intenté utilizar el método Collections.synchronizedCollection (c Collection) al pasar una nueva ArrayList y asignar 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 si utilizo un enfoque correcto y, de no ser así, ¿qué debo usar para que mi código sea seguro para subprocesos? ¡Gracias por la ayuda!


75
2018-03-14 22:18


origen


Respuestas:


Utilizar Collections.synchronizedList().

Ex:

Collections.synchronizedList(new ArrayList<YourClassNameHere>())

113
2018-03-14 23:04



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 usar Vector, que está sincronizado, pero esto es probablemente lo que yo haría.


35
2018-03-14 22:20



CopyOnWriteArrayList

Utilizar CopyOnWriteArrayList clase. Esta es la versión segura de subprocesos de ArrayList.


7
2017-07-21 08:07



podría estar usando el enfoque equivocado. El hecho de que un hilo que simula un automóvil termina antes de otro hilo de simulación de automóvil no significa que el primer hilo debería ganar la carrera simulada.

Depende mucho de su 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 usar varios hilos, puede hacer que cada carro registre el tiempo "simulado" que tomó completar la carrera, y elija al ganador como el que tenga el tiempo más corto.


6
2018-03-15 00:33



También puedes usar synchronized palabra clave para addFinisher método como este

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

Entonces puede usar ArrayList add method thread-safe de esta manera.


3
2018-03-08 15:08



Puede cambiar de ArrayList a Vector type, 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);

0
2018-03-14 23:13



Siempre que desee utilizar la versión segura de la hormiga del objeto de la colección de hormigas, tome la ayuda de java.util.concurrent. * paquete. Tiene casi toda la versión concurrente de objetos de colección no sincronizados. por ejemplo: para ArrayList, tiene java.util.concurrent.CopyOnWriteArrayList

Puedes hacer Collections.synchronizedCollection (cualquier objeto de colección), pero recuerda este clásico synchr. La técnica es costosa y viene con una sobrecarga de rendimiento. El paquete java.util.concurrent. * es menos costoso y gestiona el rendimiento de una mejor manera mediante el uso de mecanismos como

copy-on-write, compare-and-swap, Lock, iteradores de instantáneas, etc.

Por lo tanto, prefiera algo del paquete java.util.concurrent. *


0
2018-03-11 03:02



También puede usar como Vector en su lugar, ya que los vectores son seguros para la ejecución de subprocesos y los de arrays no. Aunque los vectores son viejos pero pueden resolver su propósito fácilmente.

Pero puede hacer que su Arraylist se sincronice como el código dado a esto:

Collections.synchronizedList(new ArrayList(numberOfRaceCars())); 

0
2018-06-11 05:00