如何使我的数组列表线程安全? Java 中解决问题的另一种方法?

我有一个 ArrayList,我想用它来保存 RaceCar 对象,这些对象在完成执行后立即扩展 Thread 类。一个名为 Race 的类使用 RaceCar 对象在完成执行时调用的回调方法处理此 ArrayList。回调方法 addFinisher (RaceCar finisher)将 RaceCar 对象添加到 ArrayList。这应该给出 Threads 完成执行的顺序。

我知道 ArrayList 不是同步的,因此不是线程安全的。我尝试通过传入一个新的 ArrayList 并将返回的 Collection 分配给 ArrayList 来使用 Collections.synizedCollection (c Collection)方法。然而,这给了我一个编译器错误:

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

我需要知道的是,我是否使用了正确的方法,如果没有,我应该使用什么来使我的代码线程安全?谢谢你的帮助!

217727 次浏览

改变

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)

List 是 ArrayList 的超类型,因此需要指定。

不然的话,你现在做的看起来还不错。另一个选项是您可以使用 Vector,它是同步的,但是这可能是我要做的。

使用 Collections.synchronizedList()

例如:

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

您可以将 ArrayList 更改为 Vector 类型,其中每个方法都是同步的。

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

也许吧使用了错误的方法。仅仅因为一个模拟赛车的线程在另一个赛车模拟线程之前完成,并不意味着第一个线程应该赢得模拟比赛。

这在很大程度上取决于您的应用程序,但是最好使用一个线程以较小的时间间隔计算所有赛车的状态,直到比赛结束。或者,如果您喜欢使用多个线程,您可以让每辆车记录完成比赛所需的“模拟”时间,然后选择时间最短的赢家。

也可以像这样对 addFinisher方法使用 synchronized关键字

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

So you can use ArrayList add method thread-safe with this way.

CopyOnWriteArrayList

使用 CopyOnWriteArrayList类。这是线程安全版本的 ArrayList

每当你想使用蚂蚁线程安全版本的蚂蚁收集对象,采取的帮助 并发软件包。 它几乎拥有所有非同步集合对象的并发版本。例如: 对于 ArrayList,有 java.util.while。CopyOnWriteArrayList

您可以执行 Collections.synizedCollection (任何集合对象) ,但是请记住,这种经典的 synchr.technology 是昂贵的,并且会带来性能开销。 并发. * 包开销较小,并且通过使用以下机制以更好的方式管理性能

即写即拷、比较并交换、锁定、快照迭代器等。

因此,更喜欢 java.util.conuld.* 包中的内容

您也可以使用 Vector,因为 Vector 是线程安全的,而 arraylist 不是。 虽然载体是老的,但他们可以很容易地解决你的目的。

但是你可以让你的数组列表像下面的代码一样同步:

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