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

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


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

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 (eg, manually or via a wrapper).


ArrayList不通过http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html进行同步


ArrayList is not synchronized out of the box.

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.)

This avoids some performance issues in situations where you know that you won't need thread safety (eg, 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:

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 comes in a variety of useful flavors, however, while Vector does not. My personal favorite is the 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.

CopyOnWriteArrayLists are tremendously useful in GUI work, especially in situations where you are displaying an updating set of data (eg, 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.

链接地址: http://www.djcxy.com/p/76106.html

上一篇: 为什么我需要重写Java中的equals和hashCode方法?

下一篇: 为什么当我们已经有矢量时需要同步ArrayList?