说起Vector,我们总是会想到,它与 ArrayList 一样都是 List 的子类,与 ArrayList 不同的是: Vector 是线程安全的。
使用 Vector 是多线程下解决 ArrayList 非同步问题的解决方式之一,还可以使用 Collections.SynchronizedList 或 CopyOnWriteArrayList(并发编程推荐使用)。
在 Java 1.8-API源码学习之 java.util.ArrayList 中,已经看过了 ArrayList 的一些特性,
对比 ArrayList 来说,它也有自己的特性,下面先来看一下两者的特性总结:
ArrayList | Vector | |
是否线程安全 | 否 | 是 |
底层数据结构 | Object 类型的 数组 | Object 类型的 数组 |
初始化数组的时机 | 第一次添加数据的时候 | 对象被创建的时候 |
初始化数组长度 | 10 | 10 |
数组扩容机制 | 1.5 倍,代码写死的,不可以自己设定 | 默认是 2 倍,可以自己设定 |
底层实现数组拷贝的方法 | 调用 Arrays.copyOf() | 调用 Arrays.copyOf() |
看完了 Vector 的这些特性,我们接下来看一下源码是怎样实现的:
1、Vector
1.1、对象的创建
调用空参构造方法:
有源码分析,我们得出结论,在 new Vector() 时做了两件事情:
- 创建了一个 长度为 10 的 Object 类型的 数组用来存储数据。
- 将数组扩容增长因子的值设置为默认值 0.
其他的构造方法就不解释了,相信聪明的你可以秒懂。
1.2、添加元素
调用 add(E e) 方法添加第 11 个元素:
从上面源码分析,可以得出结论:
- Vector 是线程安全的。因为它涉及数据操作且暴露出去的方法加了 synchronized 关键字保证了线程同步。这也导致了 Vector 的效率要比 ArrayList 低一些。synchronized 属于重锁,并发编程不建议使用 Vector(建议使用CopyOnWriteArrayList)。
- 每次添加元素,都会进行判断,如果当前所需容量大于了数组长度,就需要进行扩容。
- Vector 扩容的机制:默认是扩容到原来的 2 倍(可以自己设定)。
- 可以使用1个参数的构造方法,设置数组扩容增长因子,指定每次扩多长。
- 扩容使用的方法是 Arrays.copyOf() 方法进行数组的拷贝。
测试 Vector 在多线程环境下,是否是安全的:
public static void main(String[] args) {
List<String> list = new Vector<>();
for (int i = 1; i <= 100; i++) { //循环创建 100 个线程同时操作 Vector
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
运行程序,看看是否会抛出 ConcurrentModificationException 并发修改异常,如果没有,则测试成功。