如何使我的 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:45:07  来源:igfitidea点击:

How do I make my ArrayList Thread-Safe? Another approach to problem in Java?

javamultithreadingcollectionssynchronizationarraylist

提问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 synchronizedkeyword for addFinishermethod 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 CopyOnWriteArrayListclass. This is the thread safe version of ArrayList.

使用CopyOnWriteArrayList类。这是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()));