java 当我们已经有了 Vectors 时,为什么我们需要同步的 ArrayLists?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2104719/
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-10-29 19:28:44  来源:igfitidea点击:

Why do we need synchronized ArrayLists when we already have Vectors?

java

提问by giri

When do we use synchronized ArrayList? We already have Vectorwhich is synchronized.

我们什么时候使用同步ArrayList?我们已经有了Vector同步的。

回答by Uri

I think that you've got this wrong. ArrayList is unsynchronized, Vector is.

我认为你弄错了。ArrayList 未同步,Vector 为

Being synchronized means that every operation is thread safe - if you use the same vector from two threads at the same time, they can't corrupt the state. However, this makes it slower.

同步意味着每个操作都是线程安全的——如果你同时使用来自两个线程的相同向量,它们不会破坏状态。但是,这会使它变慢。

If you are working in a single threaded environment (or the list is limited to a thread and never shared), use ArrayList. If you are working with multiple threads that share the same collection, either use Vector, or use ArrayList but synchronize in some other way (e.g., manually or via a wrapper).

如果您在单线程环境中工作(或者列表仅限于一个线程并且从不共享),请使用 ArrayList。如果您正在使用共享同一集合的多个线程,请使用 Vector 或使用 ArrayList 但以某种其他方式进行同步(例如,手动或通过包装器)。

回答by Rob Spieldenner

回答by Bob Cross

ArrayList is not synchronized out of the box.

ArrayList 不是开箱即用的同步。

Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)

List 接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括 null。除了实现 List 接口之外,该类还提供了操作内部用于存储列表的数组大小的方法。(这个类大致相当于 Vector,只是它是不同步的。)

This avoids some performance issues in situations where you know that you won't need thread safety (e.g., entirely encapsulated private data). However both ArrayList and Vector have issues when using iterators over them: when iterating through either type of collection, if data is added or removed, you will throw a ConcurrentModificationException:

这可以避免在您知道不需要线程安全的情况下的一些性能问题(例如,完全封装的私有数据)。然而,ArrayList 和 Vector 在对它们使用迭代器时都有问题:在迭代任一类型的集合时,如果添加或删除数据,您将抛出 ConcurrentModificationException

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

List list = Collections.synchronizedList(new ArrayList(...));

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

请注意,此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。(结构修改是添加或删除一个或多个元素,或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)这通常是通过同步一些自然封装的对象来完成的列表。如果不存在这样的对象,则应使用 Collections.synchronizedList 方法“包装”该列表。这最好在创建时完成,以防止对列表的意外不同步访问:

List list = Collections.synchronizedList(new ArrayList(...));

此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法外,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是冒着在未来不确定的时间出现任意、非确定性行为的风险。

请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。

ArrayList comes in a variety of useful flavors, however, while Vector does not. My personal favorite is the CopyOnWriteArrayList:

然而,ArrayList 有多种有用的风格,而 Vector 没有。我个人最喜欢的是CopyOnWriteArrayList

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created. Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

ArrayList 的线程安全变体,其中所有可变操作(添加、设置等)都是通过制作底层数组的新副本来实现的。

这通常成本太高,但是当遍历操作的数量大大超过突变时可能比替代方法更有效,并且在您不能或不想同步遍历但需要排除并发线程之间的干扰时很有用。“快照”样式的迭代器方法使用对创建迭代器时数组状态的引用。这个数组在迭代器的生命周期内永远不会改变,所以干扰是不可能的,并且迭代器保证不会抛出 ConcurrentModificationException。自创建迭代器以来,迭代器不会反映对列表的添加、删除或更改。不支持迭代器本身的元素更改操作(删除、设置和添加)。这些方法抛出 UnsupportedOperationException。

CopyOnWriteArrayLists are tremendously useful in GUI work, especially in situations where you are displaying an updating set of data (e.g., moving icons on a screen). If you can tolerate having your displayed list of data be one frame out of date (because your producer thread is slightly behind your graphical update thread), CopyOnWriteArrayLists are the perfect data structure.

CopyOnWriteArrayLists 在 GUI 工作中非常有用,尤其是在您显示更新数据集的情况下(例如,在屏幕上移动图标)。如果您可以容忍显示的数据列表过时一帧(因为您的生产者线程稍微落后于图形更新线程),那么 CopyOnWriteArrayLists 是完美的数据结构。

回答by jldupont

What does it mean array list is synchronized in java?

java中的数组列表是同步的是什么意思?

It means it is thread-safe.

这意味着它是线程安全的。

  • Vectors are synchronized. Any method that touches the Vector's contents is thread safe.
  • ArrayList, on the other hand, is unsynchronized, making them, therefore, not thread safe.
  • 向量是同步的。任何接触 Vector 内容的方法都是线程安全的。
  • 另一方面,ArrayList 是不同步的,因此它们不是线程安全的。

回答by Tom

I read ArrayList is synchronized in java..

我读到 ArrayList is synchronized in java ..

But the array list apisays that

但是数组列表 api

Note that this implementation is not synchronized

注意这个实现不是同步的

So you use an ArrayList when you are sure that you wont be dealing with concurrency. Using Vector might be an overkill, and mayresult in performance issues.

因此,当您确定不会处理并发时,您可以使用 ArrayList。使用 Vector 可能有点矫枉过正,并可能导致性能问题。