为什么 Java Vector(和 Stack)类被认为已过时或已弃用?
为什么 Java Vector 被视为遗留类、已过时或已弃用?
在处理并发时它的使用不是有效的吗?
如果我不想手动同步对象,只想使用线程安全集合,而不需要制作底层数组的新副本(如 CopyOnWriteArrayList 所做的那样),那么可以使用向量
?
Stack
怎么样,它是 Vector
的子类,我应该用什么来代替它?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Vector
同步每个单独的操作。这几乎从来都不是你想做的事。通常,您希望同步整个序列的操作。同步各个操作都不太安全(例如,如果您迭代
Vector
,您仍然需要取出锁以避免其他人同时更改集合,这会导致 < code>ConcurrentModificationException 在迭代线程中)但也更慢(为什么要重复取出锁,而一次就足够了)?当然,即使您不需要,它也有锁定的开销。
基本上,在大多数情况下,这是一种非常有缺陷的同步方法。正如 Brian Henk 先生指出的那样,您可以使用诸如
Collections.synchronizedList
-Vector
结合了“调整大小的数组”集合实现与“同步每个操作”位是糟糕设计的另一个例子;装饰方法可以更清晰地分离关注点。至于
Stack
等效项 - 我会首先查看Deque
/ArrayDeque
。Vector
synchronizes on each individual operation. That's almost never what you want to do.Generally you want to synchronize a whole sequence of operations. Synchronizing individual operations is both less safe (if you iterate over a
Vector
, for instance, you still need to take out a lock to avoid anyone else changing the collection at the same time, which would cause aConcurrentModificationException
in the iterating thread) but also slower (why take out a lock repeatedly when once will be enough)?Of course, it also has the overhead of locking even when you don't need to.
Basically, it's a very flawed approach to synchronization in most situations. As Mr Brian Henk pointed out, you can decorate a collection using the calls such as
Collections.synchronizedList
- the fact thatVector
combines both the "resized array" collection implementation with the "synchronize every operation" bit is another example of poor design; the decoration approach gives cleaner separation of concerns.As for a
Stack
equivalent - I'd look atDeque
/ArrayDeque
to start with.Vector 是 1.0 的一部分——最初的实现有两个缺点:
1.命名:向量实际上只是可以作为数组访问的列表,因此它应该被称为
ArrayList
(这是Vector
的Java 1.2 Collections替代品) 。2.并发:所有
get()
、set()
方法都是同步
,因此您无法进行细粒度控制过度同步。ArrayList
和Vector
之间没有太大区别,但您应该使用ArrayList
。来自 API 文档。
Vector was part of 1.0 -- the original implementation had two drawbacks:
1. Naming: vectors are really just lists which can be accessed as arrays, so it should have been called
ArrayList
(which is the Java 1.2 Collections replacement forVector
).2. Concurrency: All of the
get()
,set()
methods aresynchronized
, so you can't have fine grained control over synchronization.There is not much difference between
ArrayList
andVector
, but you should useArrayList
.From the API doc.
除了已经给出的关于使用 Vector 的答案之外,Vector 还提供了一些与 List 接口不同的关于枚举和元素检索的方法,开发人员(尤其是那些学习过 1.2 之前的 Java 的开发人员)可以倾向于使用它们,如果他们处于代码。尽管枚举速度更快,但它们不会检查集合在迭代期间是否被修改,这可能会导致问题,并且考虑到可能会选择 Vector 进行同步 - 伴随着来自多个线程的访问,这使其成为一个特别有害的问题。使用这些方法还会将大量代码耦合到 Vector,因此用不同的 List 实现替换它并不容易。
Besides the already stated answers about using Vector, Vector also has a bunch of methods around enumeration and element retrieval which are different than the List interface, and developers (especially those who learned Java before 1.2) can tend to use them if they are in the code. Although Enumerations are faster, they don't check if the collection was modified during iteration, which can cause issues, and given that Vector might be chosen for its syncronization - with the attendant access from multiple threads, this makes it a particularly pernicious problem. Usage of these methods also couples a lot of code to Vector, such that it won't be easy to replace it with a different List implementation.
java.util.Stack 继承了 java.util.Vector 的同步开销,这通常是不合理的。
但它继承的远不止于此。
java.util.Stack 扩展了 java.util.Vector
是面向对象设计中的一个错误。纯粹主义者会注意到,它还提供了许多超出传统上与堆栈相关的操作的方法(即:push、pop、peek、size)。还可以执行search
、elementAt
、setElementAt
、remove
和许多其他随机访问操作。基本上由用户决定是否避免使用 Stack 的非堆栈操作。由于这些性能和 OOP 设计原因,JavaDoc for
java.util.Stack
推荐ArrayDeque
作为自然的替代品。 (双端队列不仅仅是一个堆栈,但至少它仅限于操作两端,而不是提供对所有内容的随机访问。)java.util.Stack
inherits the synchronization overhead ofjava.util.Vector
, which is usually not justified.It inherits a lot more than that, though. The fact that
java.util.Stack extends java.util.Vector
is a mistake in object-oriented design. Purists will note that it also offers a lot of methods beyond the operations traditionally associated with a stack (namely: push, pop, peek, size). It's also possible to dosearch
,elementAt
,setElementAt
,remove
, and many other random-access operations. It's basically up to the user to refrain from using the non-stack operations ofStack
.For these performance and OOP design reasons, the JavaDoc for
java.util.Stack
recommendsArrayDeque
as the natural replacement. (A deque is more than a stack, but at least it's restricted to manipulating the two ends, rather than offering random access to everything.)您可以使用 java.util.Collection 中的 >synchronizedCollection/List 方法从非线程安全集合获取线程安全集合。
You can use the synchronizedCollection/List method in
java.util.Collection
to get a thread-safe collection from a non-thread-safe one.