Как сделать мой ArrayList потокобезопасным? Другой подход к проблеме в Java?

У меня есть ArrayList, который я хочу использовать для хранения объектов RaceCar, которые расширяют класс Thread, как только они закончатся. Класс, называемый Race, обрабатывает этот ArrayList, используя метод обратного вызова, который вызывает объект RaceCar, когда он завершен. Метод обратного вызова addFinisher (финишер RaceCar) добавляет объект RaceCar в ArrayList. Предполагается, что он должен выполнить порядок выполнения Threads.

Я знаю, что ArrayList не синхронизирован и, следовательно, не является потокобезопасным. Я попытался использовать метод Collections.synchronizedCollection(c Collection), передав новый ArrayList и назначив возвращенную коллекцию ArrayList. Однако это дает мне ошибку компилятора:

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

Вот соответствующий код:

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

Что мне нужно знать, я использую правильный подход, а если нет, то что я должен использовать, чтобы сделать мой код потокобезопасным? Спасибо за помощь!

Ответ 2

Измените

private ArrayList finishingOrder;

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

к

private List finishingOrder;

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

Список - это супертип ArrayList, поэтому вам нужно указать это.

В противном случае то, что вы делаете, кажется прекрасным. Другой вариант - вы можете использовать Vector, который синхронизирован, но это, вероятно, то, что я сделал бы.

Ответ 4

Возможно, вы используете неправильный подход. Просто потому, что один поток, который имитирует завершение автомобиля перед другой машинной нитью моделирования, не означает, что первая нить должна выиграть имитированную гонку.

Это зависит от вашего приложения, но может быть лучше иметь один поток, который вычисляет состояние всех автомобилей с небольшими интервалами времени, пока гонка не будет завершена. Или, если вы предпочитаете использовать несколько потоков, у вас может быть каждая запись автомобиля "смоделированное" время, необходимое для завершения гонки, и выбрать победителя как самого короткого времени.

Ответ 5

Вы также можете использовать ключевое слово synchronized для метода addFinisher, подобного этому

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

Таким образом, вы можете использовать метод ArrayList для потоковой передачи таким образом.

Ответ 6

Вы можете перейти от ArrayList к типу Vector, в котором каждый метод синхронизирован.

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

Ответ 7

Всякий раз, когда вы хотите использовать ant потокобезопасную версию объекта коллекции ant, обратитесь за помощью к пакету java.util.concurrent. *. Он имеет почти все параллельные версии несинхронизированных объектов коллекции. например: для ArrayList у вас есть java.util.concurrent.CopyOnWriteArrayList

Вы можете сделать Collections.synchronizedCollection(любой объект коллекции), но помните этот классический синхр. техника дорогая и имеет накладные расходы. java.util.concurrent. * пакет дешевле и лучше управляет производительностью, используя такие механизмы, как

copy-on-write, compare-and-swap, блокировки, итераторы моментальных снимков и т.д.

Итак, Предпочитаю что-то из java.util.concurrent. * package