Frage Wie mache ich meine ArrayList Thread-Safe? Ein anderer Ansatz für Probleme in Java?


Ich habe eine ArrayList, mit der ich RaceCar-Objekte aufnehmen kann, die die Thread-Klasse erweitern, sobald sie fertig sind. Eine Klasse namens Race behandelt diese ArrayList mit einer Callback-Methode, die das RaceCar-Objekt aufruft, wenn die Ausführung abgeschlossen ist. Die Callback-Methode addFinisher (RaceCar-Finisher) fügt der ArrayList das RaceCar-Objekt hinzu. Dies soll die Reihenfolge angeben, in der die Threads die Ausführung beenden.

Ich weiß, dass ArrayList nicht synchronisiert ist und somit nicht Thread-sicher ist. Ich habe versucht, die Collections.synchronizedCollection (c Collection) -Methode zu verwenden, indem ich eine neue ArrayList übergeben und die zurückgegebene Collection einer ArrayList zuweisen. Dies gibt mir jedoch einen Compilerfehler:

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

Hier ist der relevante Code:

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);
    }

Was ich wissen muss ist, verwende ich einen korrekten Ansatz und wenn nicht, was sollte ich verwenden, um meinen Code threadsicher zu machen? Danke für die Hilfe!


75
2018-03-14 22:18


Ursprung


Antworten:


Benutzen Collections.synchronizedList().

Ex:

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

113
2018-03-14 23:04



Veränderung

private ArrayList finishingOrder;

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

zu

private List finishingOrder;

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

List ist ein Supertyp von ArrayList, daher müssen Sie dies angeben.

Ansonsten scheint das, was du tust, in Ordnung zu sein. Andere Option ist, dass Sie Vector verwenden können, der synchronisiert wird, aber das ist wahrscheinlich, was ich tun würde.


35
2018-03-14 22:20



CopyOnWriteArrayList

Benutzen CopyOnWriteArrayList Klasse. Dies ist die Thread-sichere Version von ArrayList.


7
2017-07-21 08:07



Sie Macht verwende den falschen Ansatz. Nur weil ein Thread, der ein Auto simuliert, vor einem anderen Auto-Simulations-Thread endet, bedeutet das nicht, dass der erste Thread das simulierte Rennen gewinnen sollte.

Es hängt viel von Ihrer Anwendung ab, aber es ist vielleicht besser, einen Thread zu haben, der den Zustand aller Autos in kleinen Zeitabständen bis zum Ende des Rennens berechnet. Oder, wenn Sie mehrere Threads verwenden möchten, können Sie jedes Auto die "simulierte" Zeit aufzeichnen, die es brauchte, um das Rennen zu beenden, und den Gewinner als den mit der kürzesten Zeit auswählen.


6
2018-03-15 00:33



Sie können auch verwenden synchronized Stichwort für addFinisher Methode so

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

Auf diese Weise können Sie die ArrayList-Add-Methode thread-safe verwenden.


3
2018-03-08 15:08



Sie können von ArrayList zu Vektortyp wechseln, in dem jede Methode synchronisiert wird.

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

0
2018-03-14 23:13



Wann immer Sie eine ant-thread-fähige Version des Ameisen-Sammlungsobjekts verwenden möchten, nehmen Sie Hilfe von java.util.concurrent. * Paket. Es hat fast alle gleichzeitige Versionen unsynchronisierter Auflistungsobjekte. zB: für ArrayList haben Sie java.util.concurrent.CopyOnWriteArrayList

Sie können Collections.synchronizedCollection (jedes Auflistungsobjekt) ausführen, aber denken Sie an diese klassische Synchronisierung. Technik ist teuer und kommt mit Overhead-Aufwand. java.util.concurrent. * Paket ist weniger teuer und verwaltet die Leistung in besserer Weise durch die Verwendung von Mechanismen wie

Copy-on-Write, Vergleichen und Tauschen, Lock, Snapshot-Iteratoren, etc.

Also, bevorzugen Sie etwas von java.util.concurrent. * Paket


0
2018-03-11 03:02



Sie können auch stattdessen als Vektor verwenden, da Vektoren Thread-sicher sind und Arraylist nicht. Obwohl Vektoren alt sind, aber sie können Ihren Zweck leicht lösen.

Aber Sie können Ihre Arraylist folgendermaßen synchronisieren lassen:

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

0
2018-06-11 05:00