如何使我的 ArrayList 线程安全?Java中解决问题的另一种方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2444005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I make my ArrayList Thread-Safe? Another approach to problem in Java?
提问by ericso
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.
我有一个 ArrayList,我想用它来保存 RaceCar 对象,一旦它们完成执行,就扩展 Thread 类。一个名为 Race 的类使用 RaceCar 对象在完成执行时调用的回调方法来处理此 ArrayList。回调方法 addFinisher(RaceCar finisher) 将 RaceCar 对象添加到 ArrayList。这应该给出线程完成执行的顺序。
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:
我知道 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));
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!
我需要知道的是,我是否使用了正确的方法,如果没有,我应该使用什么来使我的代码线程安全?谢谢您的帮助!
采纳答案by Amir Afghani
Use Collections.synchronizedList()
.
使用Collections.synchronizedList()
.
Ex:
前任:
Collections.synchronizedList(new ArrayList<YourClassNameHere>())
回答by Reverend Gonzo
Change
改变
private ArrayList finishingOrder;
//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars)
to
到
private List finishingOrder;
//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedList(new ArrayList(numberOfRaceCars)
List is a supertype of ArrayList so you need to specify that.
List 是 ArrayList 的超类型,因此您需要指定它。
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.
否则,你在做什么似乎很好。另一个选择是您可以使用同步的 Vector,但这可能是我会做的。
回答by darlinton
You can change from ArrayList to Vector type, in which every method is synchronized.
您可以从 ArrayList 更改为 Vector 类型,其中每个方法都是同步的。
private Vector finishingOrder;
//Make a Vector to hold RaceCar objects to determine winners
finishingOrder = new Vector(numberOfRaceCars);
回答by erickson
You mightbe 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.
这在很大程度上取决于您的应用程序,但最好让一个线程以较小的时间间隔计算所有汽车的状态,直到比赛结束。或者,如果您更喜欢使用多个线程,您可以让每辆车记录完成比赛所需的“模拟”时间,并选择时间最短的获胜者。
回答by erhun
You can also use synchronized
keyword for addFinisher
method like this
您也可以使用synchronized
关键字作为这样的addFinisher
方法
//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.
因此,您可以通过这种方式使用 ArrayList 添加方法线程安全。
回答by Singh Piyush
CopyOnWriteArrayList
CopyOnWriteArrayList
Use CopyOnWriteArrayList
class. This is the thread safe version of ArrayList
.
回答by Jaydeep Ramesh Deshmukh
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
每当您想使用 ant 线程安全版本的 ant 集合对象时,请借助java.util.concurrent.*包。它拥有几乎所有非同步集合对象的并发版本。例如:对于 ArrayList,你有 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
你可以做 Collections.synchronizedCollection(任何集合对象),但要记住这个经典的同步。技术是昂贵的,并且伴随着性能开销。java.util.concurrent.* 包更便宜,并通过使用类似的机制以更好的方式管理性能
copy-on-write,compare-and-swap,Lock,snapshot iterators,etc.
写时复制、比较和交换、锁定、快照迭代器等。
So,Prefer something from java.util.concurrent.* package
所以,更喜欢 java.util.concurrent.* 包中的东西
回答by Naman jain
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.
您也可以使用 as Vector 代替,因为向量是线程安全的,而 arraylist 不是。尽管矢量很旧,但它们可以轻松解决您的问题。
But you can make your Arraylist synchronized like code given this:
但是你可以让你的 Arraylist 像代码一样同步:
Collections.synchronizedList(new ArrayList(numberOfRaceCars()));