使用并发处理时,其使用无效吗?
如果我不想手动同步对象并且只想使用线程安全的集合而不需要创建基础数组的新副本(就像
CopyOnWriteArrayList
一样),那么使用Vector
可以吗?关于
Stack
呢? Vector
的子类,我应该用它代替什么?#1 楼
Vector
在每个单独的操作上同步。 通常,您想要同步整个操作序列。同步单个操作既不安全(例如,如果您遍历
Vector
,则仍然需要锁住以避免其他人同时更改集合,这将导致在迭代线程中产生ConcurrentModificationException
),但同时慢一些(为什么一次就够了,为什么要反复取一个锁)?当然,即使您不需要时,它也有锁的开销。
基本上,在大多数情况下,这是一种非常有缺陷的同步方法。正如Brian Henk先生所指出的那样,您可以使用诸如
Collections.synchronizedList
之类的调用来装饰集合-Vector
将“调整大小的数组”集合实现与“同步每个操作”位结合在一起的事实是设计欠佳的另一个例子。装饰方法可以使关注点更清晰地分离。对于
Stack
等效项-我先来看Deque
/ ArrayDeque
。评论
“通常,您要同步整个操作序列。” - 这就是重点!谢谢!
– fjsj
09年9月7日,0:56
在哪个版本的Java Deprecated Vector中(当前我使用Java7)。但是我从来没有看到过Deprecated?再见了,不错的解释... + 1
– Samir Mangroliya
2012年9月9日在16:55
@Samir:尚未正式弃用-只是通常首选ArrayList。
–乔恩·斯基特(Jon Skeet)
2012年3月9日17:04
@Samir:不,我不会尝试预测未来。
–乔恩·斯基特(Jon Skeet)
2012年9月9日17:11
只是gr8。 vector不推荐使用其legacy类。不推荐使用的和legacy之间必须有区别,是的,请参见stackoverflow.com/questions/2873254/…
–令人沮丧的Shilimkar
2013年12月23日在6:23
#2 楼
Vector是1.0的一部分-原始实现有两个缺点:1。命名:向量实际上只是可以作为数组访问的列表,因此应该将其称为
ArrayList
(这是Java 1.2 Collections替代Vector
)。2。并发性:所有
get()
和set()
方法都是synchronized
,因此您无法对同步进行精细的控制。ArrayList
和Vector
之间没有太大区别,但您应该使用ArrayList
。 /> 来自API文档。
从Java 2平台v1.2开始,对该
类进行了改进以实现
List接口。 ,使其成为Java Collections Framework的成员。与
新集合的实现不同,
向量是同步的。
评论
可以作为数组访问的列表? ArrayList不是一个简短的名称,这可能就是为什么在其他地方(例如STL)使用vector的原因。
– dhardy
13年5月6日在14:48
@dhardy列出数组作为其基础实现。有ArrayList,LinkedList等,它们全部实现接口List,因此,如果您想利用List方法而不必知道底层实现的实际含义,则可以将List用作方法等的参数。同样适用于Map的实现者等。同时,C ++确实有一个std :: array类,它只是基于模板的C样式静态长度数组的替代。
– JAB
2014年5月14日15:07
#3 楼
除了已经说明的使用Vector的答案外,Vector还具有许多围绕List和List的枚举和元素检索方法,并且开发人员(尤其是那些在1.2之前学习过Java的人)可以使用它们。码。尽管枚举速度更快,但它们不会检查迭代期间是否对集合进行了修改,这可能会引起问题,并且考虑到可能会选择Vector进行同步-伴随有来自多个线程的访问,这使其成为一个特别有害的问题。这些方法的使用还将很多代码与Vector耦合在一起,因此用其他List实现替换它并不容易。#4 楼
您可以在java.util.Collection
中使用syncedCollection / List方法从非线程安全的对象中获取线程安全的集合。评论
为什么这比矢量更好?
– fjsj
09年9月6日在18:13
正如乔恩(Jon)所述,Vector的性能不佳,并且该方法允许您选择何时进行同步是一个好主意。这完全是一个设计问题。您应该在Vector上使用ArrayList,因为您应该默认为非同步访问。
–布赖恩·汉克(Brian Henk)
09年9月6日在18:22
这如何回答这个问题?
–user207421
19年4月8日在8:17
#5 楼
java.util.Stack
继承了java.util.Vector
的同步开销,通常这是不合理的。它所继承的内容远不止于此。
java.util.Stack extends java.util.Vector
在面向对象设计中是一个错误。纯粹主义者将注意到,除了传统上与堆栈相关的操作(即:推入,弹出,窥视,大小)之外,它还提供了许多方法。还可以执行search
,elementAt
,setElementAt
,remove
和许多其他随机访问操作。基本上,用户应避免使用Stack
的非堆栈操作。出于这些性能和OOP设计的原因,java.util.Stack
的JavaDoc建议使用ArrayDeque
作为自然替代品。 (双端队列不只是一个堆栈,但至少限于操作两端,而不是提供对所有内容的随机访问。)
评论
它们已过时,但不被弃用。