У меня есть список ArrayList, который я хочу использовать для хранения объектов RaceCar, расширяющих класс Thread, как только они закончат выполнение. Класс с именем Race обрабатывает этот список ArrayList с помощью метода обратного вызова, который объект RaceCar вызывает по завершении выполнения. Метод обратного вызова addFinisher (RaceCar Finisher) добавляет объект RaceCar в ArrayList. Это должно указать порядок, в котором потоки завершают выполнение.
Я знаю, что 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);
}
Что мне нужно знать, так это то, правильно ли я использую подход, а если нет, что мне следует использовать, чтобы сделать мой код потокобезопасным? Спасибо за помощь!
List
интерфейс на самом деле недостаточно полный, чтобы быть очень полезным в многопоточности.)Collections.synchronizedList()
этого у нас было бы РЕАЛЬНОЕ условие гонки: PОтветы:
Используйте
Collections.synchronizedList()
.Пример:
Collections.synchronizedList(new ArrayList<YourClassNameHere>())
источник
+ Изменить
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, поэтому вам нужно указать это.
В остальном то, что вы делаете, кажется нормальным. Другой вариант - вы можете использовать вектор, который синхронизируется, но, вероятно, я бы так поступил.
источник
List
, наверное, было бы полезнее. ИлиList<RaceCar>
.//Print out winner System.out.println("The Winner is " + ((RaceCar) finishingOrder.get(0)).toString() + "!");
он говорит, что метод get (0) не найден. Мысли?CopyOnWriteArrayList
Используйте
CopyOnWriteArrayList
класс. Это поточно-ориентированная версияArrayList
.источник
ConcurrentLinkedQueue
Вы могли бы использовать неправильный подход. Тот факт, что один поток, имитирующий автомобиль, завершается раньше, чем другой поток моделирования автомобиля, не означает, что первый поток должен выиграть имитацию гонки.
Это во многом зависит от вашего приложения, но может быть лучше иметь один поток, который вычисляет состояние всех автомобилей через небольшие промежутки времени, пока гонка не будет завершена. Или, если вы предпочитаете использовать несколько потоков, вы можете заставить каждую машину записывать «смоделированное» время, необходимое для завершения гонки, и выбирать победителя в качестве победителя с наименьшим временем.
источник
Вы также можете использовать
synchronized
ключевое слово дляaddFinisher
такого метода//Implement the one method in the RaceListener interface public synchronized void addFinisher(RaceCar finisher) { finishingOrder.add(finisher); }
Таким образом, вы можете использовать потокобезопасный метод добавления ArrayList.
источник
final Object
вместо этого каждый раз, когдаCollection
каким-либо образом получаете доступ к .Если вы хотите использовать потокобезопасную версию объекта ant-collection, воспользуйтесь помощью пакета java.util.concurrent. * . В нем есть почти все параллельные версии несинхронизированных объектов коллекции. например: для ArrayList у вас есть java.util.concurrent.CopyOnWriteArrayList
Вы можете использовать Collections.synchronizedCollection (любой объект коллекции), но помните этот классический синхронизатор. техника дорогая и требует накладных расходов. Пакет java.util.concurrent. * дешевле и лучше управляет производительностью, используя такие механизмы, как
Итак, предпочитайте что-то из пакета java.util.concurrent. *
источник
Вместо этого вы также можете использовать как Vector, поскольку векторы являются потокобезопасными, а arrayylist - нет. Хотя векторы старые, но они могут легко решить вашу задачу.
Но вы можете синхронизировать свой Arraylist, как код:
Collections.synchronizedList(new ArrayList(numberOfRaceCars()));
источник
Вы можете перейти от ArrayList к типу Vector, в котором все методы синхронизированы.
private Vector finishingOrder; //Make a Vector to hold RaceCar objects to determine winners finishingOrder = new Vector(numberOfRaceCars);
источник