it-swarm.com.de

Wie mache ich meine ArrayList Thread-sicher? Ein anderer Ansatz für ein Problem in Java?

Ich habe eine ArrayList, die ich verwenden möchte, um RaceCar-Objekte zu speichern, die die Thread-Klasse erweitern, sobald sie mit der Ausführung fertig sind. Eine Klasse namens Race verarbeitet diese ArrayList mithilfe 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 daher nicht Thread-sicher ist. Ich habe versucht, die Collections.synchronizedCollection (c Collection) -Methode zu verwenden, indem ich eine neue ArrayList übergab und die zurückgegebene Collection einer ArrayList zuweise. Dies gibt mir jedoch einen Compiler-Fehler:

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

Hier ist der entsprechende 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, benutze ich einen korrekten Ansatz und wenn nicht, was sollte ich verwenden, um meinen Code threadsicher zu machen? Danke für die Hilfe!

78
ericso

Verwenden Sie Collections.synchronizedList() .

Ex:

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

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)

Liste ist ein Supertyp von ArrayList. Sie müssen dies angeben.

Ansonsten scheint es gut zu sein, was Sie tun. Eine andere Möglichkeit ist, dass Sie Vector verwenden können, der synchronisiert ist, aber wahrscheinlich würde ich das auch tun.

35
Reverend Gonzo

CopyOnWriteArrayList

Verwenden Sie CopyOnWriteArrayList class. Dies ist die Thread-sichere Version von ArrayList .

7
Singh Piyush

Sie möglicherweise verwenden den falschen Ansatz. Nur weil ein Thread, der ein Auto simuliert, vor einem anderen Autosimulationsthread endet, bedeutet dies nicht, dass der erste Thread das simulierte Rennen gewinnen sollte.

Es hängt sehr stark von Ihrer Anwendung ab, aber es ist möglicherweise besser, einen Thread zu haben, der den Status aller Autos in kleinen Zeitintervallen berechnet, bis das Rennen abgeschlossen ist. Wenn Sie es vorziehen, mehrere Threads zu verwenden, kann jedes Fahrzeug die "simulierte" Zeit aufzeichnen, die es für das Rennen benötigt hat, und den Gewinner als den mit der kürzesten Zeit auswählen.

6
erickson

Sie können auch das synchronized-Schlüsselwort für die addFinisher-Methode wie folgt verwenden

    //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 threadsicher verwenden.

3
erhun

Wenn Sie eine ant-Thread-sichere Version des Ant-Collection-Objekts verwenden möchten, nehmen Sie die Hilfe von Java.util.concurrent. * package . Sie enthält fast alle gleichzeitigen Versionen von nicht synchronisierten Collection-Objekten. Beispiel: Für ArrayList haben Sie Java.util.concurrent.CopyOnWriteArrayList

Sie können Collections.synchronizedCollection (ein beliebiges Collection-Objekt) ausführen, denken Sie jedoch an diesen klassischen Synchr. Diese Technik ist teuer und wird mit einem Performance-Overhead geliefert. Das Paket ist weniger kostspielig und verwaltet die Leistung besser, indem Mechanismen wie verwendet werden 

copy-on-write, Compare-and-Swap, Lock, Snapshot-Iteratoren usw.

Also lieber etwas von Java.util.concurrent. * Package

Sie können stattdessen auch als Vektor verwenden, da Vektoren fadensicher sind und arraylist keine . Vektoren sind zwar alt, aber sie können Ihren Zweck leicht lösen.

Sie können Ihre Arraylist jedoch wie folgt synchronisieren:

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

Sie können von ArrayList zum Vector-Typ wechseln, bei dem jede Methode synchronisiert wird. 

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