如何使我的 ArrayList 线程安全? Java 中解决问题的另一种方法?
我有一个 ArrayList,我想用它来保存 RaceCar 对象,这些对象在执行完毕后立即扩展 Thread 类。名为 Race 的类使用 RaceCar 对象在完成执行时调用的回调方法来处理此 ArrayList。回调方法 addFinisher(RaceCar finisher) 将 RaceCar 对象添加到 ArrayList 中。这应该给出线程完成执行的顺序。
我知道 ArrayList 不是同步的,因此不是线程安全的。我尝试通过传入新的 ArrayList 并将返回的 Collection 分配给 ArrayList 来使用 Collections.synchronizedCollection(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);
}
我需要知道的是,我使用的方法是否正确,如果不正确,我应该使用什么来使我的代码线程安全?感谢您的帮助!
I have an ArrayList that I want to use to hold RaceCar objects that extend the Thread class as soon as they are finished executing. A class, called Race, handles this ArrayList using a callback method that the RaceCar object calls when it is finished executing. The callback method, addFinisher(RaceCar finisher), adds the RaceCar object to the ArrayList. This is supposed to give the order in which the Threads finish executing.
I know that ArrayList isn't synchronized and thus isn't thread-safe. I tried using the Collections.synchronizedCollection(c Collection) method by passing in a new ArrayList and assigning the returned Collection to an ArrayList. However, this gives me a compiler error:
Race.java:41: incompatible types
found : java.util.Collection
required: java.util.ArrayList
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));
Here is the relevant 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);
}
What I need to know is, am I using a correct approach and if not, what should I use to make my code thread-safe? Thanks for the help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
使用
Collections.synchronizedList()
。前任:
Use
Collections.synchronizedList()
.Ex:
更改
为
List 是 ArrayList 的超类型,因此您需要指定它。
否则,你正在做的事情看起来不错。另一种选择是你可以使用 Vector,它是同步的,但这可能就是我会做的。
Change
to
List is a supertype of ArrayList so you need to specify that.
Otherwise, what you're doing seems fine. Other option is you can use Vector, which is synchronized, but this is probably what I would do.
CopyOnWriteArrayList
使用
CopyOnWriteArrayList
类。这是ArrayList
。
CopyOnWriteArrayList
Use
CopyOnWriteArrayList
class. This is the thread safe version ofArrayList
.您还可以在
addFinisher
方法中使用synchronized
关键字,这样您就可以通过这种方式使用 ArrayList add 方法线程安全。
You can also use
synchronized
keyword foraddFinisher
method like thisSo you can use ArrayList add method thread-safe with this way.
您可能使用了错误的方法。仅仅因为模拟汽车的一个线程在另一个汽车模拟线程之前完成并不意味着第一个线程应该赢得模拟比赛。
这在很大程度上取决于您的应用程序,但最好有一个线程以较小的时间间隔计算所有汽车的状态,直到比赛完成。或者,如果您更喜欢使用多线程,您可以让每辆车记录完成比赛所需的“模拟”时间,并选择时间最短的获胜者。
You might be using the wrong approach. Just because one thread that simulates a car finishes before another car-simulation thread doesn't mean that the first thread should win the simulated race.
It depends a lot on your application, but it might be better to have one thread that computes the state of all cars at small time intervals until the race is complete. Or, if you prefer to use multiple threads, you might have each car record the "simulated" time it took to complete the race, and choose the winner as the one with shortest time.
每当你想使用 ant 线程安全版本的 ant 集合对象时,请借助 java.util.concurrent.* 包。
它几乎拥有所有并发版本的不同步集合对象。例如:对于ArrayList,您有java.util.concurrent.CopyOnWriteArrayList
您可以执行Collections.synchronizedCollection(任何集合对象),但请记住这个经典的synchr。该技术非常昂贵并且会带来性能开销。
java.util.concurrent.* 包成本较低,并且通过使用类似机制以更好的方式管理性能
所以,更喜欢 java.util.concurrent.* 包中的东西
Whenever you want to use ant thread safe version of ant collection object,take help of java.util.concurrent.* package.
It has almost all concurrent version of unsynchronized collection objects. eg: for ArrayList, you have java.util.concurrent.CopyOnWriteArrayList
You can do Collections.synchronizedCollection(any collection object),but remember this classical synchr. technique is expensive and comes with performence overhead.
java.util.concurrent.* package is less expensive and manage the performance in better way by using mechanisms like
So,Prefer something from java.util.concurrent.* package
您也可以使用 as Vector 来代替,因为向量是线程安全的,而 arraylist 不是。
虽然向量很旧,但它们可以轻松解决您的目的。
但是您可以像下面的代码一样使您的 Arraylist 同步:
You can also use as Vector instead, as vectors are thread safe and arraylist are not.
Though vectors are old but they can solve your purpose easily.
But you can make your Arraylist synchronized like code given this:
您可以从 ArrayList 更改为 Vector 类型,其中每个方法都是同步的。
You can change from ArrayList to Vector type, in which every method is synchronized.