您的位置:首页 > 编程语言 > Java开发

JDK1.8源码阅读系列之三:Vector_1

2017-02-05 20:43 393 查看
  

  本篇随笔主要描述的是我阅读 Vector 源码期间的对于 Vector 的一些实现上的个人理解,用于个人备忘,有不对的地方,请指出~

  先来看一下 Vector 的继承图:  

  可以看出,Vector 的直接父类是 AbstractList(已在JDK1.8源码阅读系列之一介绍过), 直接子类是
Stack(下一篇文章介绍)。

  在 Vector 类源码中,我认为有以下几个地方值得注意:

  1、Vector 类几乎对每一个独立操作(除 Iterator 相关方法)都实现了同步,即在每个方法上几乎都增加了 synchronized 关键字来实现线程间的同步。

  

  2、Vector 扩容方法 grow()

1  private void grow(int minCapacity) {
2         // overflow-conscious code
3         int oldCapacity = elementData.length;
4         int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
5                                          capacityIncrement : oldCapacity);
6         if (newCapacity - minCapacity < 0)
7             newCapacity = minCapacity;
8         if (newCapacity - MAX_ARRAY_SIZE > 0)
9             newCapacity = hugeCapacity(minCapacity);
10         elementData = Arrays.copyOf(elementData, newCapacity);
11 }


 

  可见 Vector 的扩容量是由 oldCapacity 与 capacityIncrement 共同决定的,capacityIncrement 是我们可控的一个参数,在构造方法中传入,即每次容量具体增加多少,如果我们在创建 Vector 对象是没有指定 capacityIncrement,则默认每次把容量增加为原来的二倍(不越界的情况下)。

  3、Vector 类中的 subList()方法我认为值得注意,源码如下:

1 public synchronized List<E> subList(int fromIndex, int toIndex) {
2         return Collections.synchronizedList(super.subList(fromIndex, toIndex),
3                                             this);
4 }


  可见 Vector 调用的是其父类 AbstractList 类中的 subList 方法,并利用 Collections.synchronizedList() 进行装饰,下面看下 Collections.synchronizedList() 方法:

public class Collections {
......
static <T> List<T> synchronizedList(List<T> list, Object mutex) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list, mutex) :
new SynchronizedList<>(list, mutex));
}
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;

final List<E> list;

SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
......
}

......
}


  可见 Collections.synchronizedList() 方法中传入的两个参数 一个是用于底层数组操作的 list,一个是信号量,用于线程间同步。在 vector 类的 subList 方法中,我们传入的参数为 AbstractList 类 subList 方法产生的基于 vector 的 list(对此 list 上进行的操作都会反应到 vector 当中去),还有把 vector 作为信号量参数传入,之所以要把 vector 对象作为信号量,是因为产生的
subList 底层是基于 vector 的,对此 subList 上进行的同步操作应与 vector 上进行的同步操作条件相同,防止同步出现问题。

  4、为什么java 
Vector
类被认为是一个遗留的,过时的或废弃的类?在并发操作时,使用它是无效的吗?

  Vector中对每一个独立操作都实现了同步,这通常不是我们想要的做法。对单一操作实现同步通常不是线程安全的(举个例子,比如你想遍历一个Vector实例。你仍然需要申明一个锁来防止其他线程在同一时刻修改这个Vector实例。如果不添加锁的话通常会在遍历实例的这个线程中导致一个
ConcurrentModificationException
)同时这个操作也是十分慢的(在创建了一个锁就已经足够的前提下,为什么还需要重复的创建锁)当然,即使你不需要同步,Vector也是有锁的资源开销的。

  总的来说,在大多数情况下,这种同步方法是存在很大缺陷的。正如Mr Brain Henk指出,你可以通过用
Collections.synchronizedList
来装饰一个集合 ,事实上 ,
Vector
 将“可变数组”的集合实现与“同步每一个方法”结合起来的做法是另一个糟糕的设计。

  各个装饰方法能够更明确的指示其关注的功能实现。

  对于其子类 Stack ,也可使用双端队列
Deque/ArrayDeque
来实现栈操作,比如:

  

1 public static void main(String[] args) {
2         Deque<Integer> deque = new ArrayDeque<>();
3         deque.push(1);
4         deque.push(2);
5         deque.push(3);
6         System.out.println(deque.peek());//返回栈顶元素 不删除
7         System.out.println(deque.size());
8         while (!deque.isEmpty()) {
9             System.out.println(deque.pop());
10         }
11 }


 

 

 

  参考:https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/why-is-java-vector-class-considered-obsolete-or-deprecated.md

   

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: