Vector
Vector
是 Java 中的一个线程安全的类,它实现了动态数组的数据结构。与 ArrayList
类似,Vector
可以存储任意类型的对象,并且支持动态增长和缩减容量。
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();
// 线程1:向 Vector 中添加元素
Thread thread1 = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
vector.add(i);
System.out.println("线程1添加元素:" + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 线程2:从 Vector 中移除元素
Thread thread2 = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
if (!vector.isEmpty()) {
int removedElement = vector.remove(0);
System.out.println("线程2移除元素:" + removedElement);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 启动线程
thread1.start();
thread2.start();
// 等待两个线程执行结束
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印 Vector 中剩余的元素
System.out.println("剩余元素:" + vector);
}
}
CopyOnWriteArrayList
CopyOnWriteArrayList
是 Java 中的线程安全集合类,是一种并发容器,它提供了一种并发访问列表的方式。它的特点是在进行写操作(添加、修改、删除元素)时,会创建一个新的副本(即复制一份当前集合),并在副本上进行操作,从而保证原有集合的线程安全性。这意味着在进行写操作时,读操作不会被阻塞,并且读操作不需要加锁,因此读操作的性能较高。
“写人时复制”容器的迭代器保留一个指向底层基础数组的引用,这个数组当前位于迭代器的起始位置,由于它不会被修改,因此在对其进行同步时只需确保数组内容的可见性。因此,多个线程可以同时对这个容器进行迭代,而不会彼此干扰或者与修改容器的线程相互干扰。“写入时复制”容器返回的迭代器不会抛出ConcurrentModificationException,并且返回的元素与迭代器创建时的元素完全一致,而不必考虑之后修改操作所带来的影响。
显然,每当修改容器时都会复制底层数组,这需要一定的开销,特别是当容器的规模较大时。仅当迭代操作远远多于修改操作时,才应该使用“写入时复制”容器。这个准则很好地描述了许多事件通知系统:在分发通知时需要迭代已注册监听器链表,并调用每一个监听器,在大多数情况下,注册和注销事件监听器的操作远少于接收事件通知的操作
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Orange");
// 迭代元素
for (String fruit : list) {
System.out.println(fruit);
}
// 修改元素(会创建副本)
list.set(0, "Grapes");
// 删除元素(会创建副本)
list.remove("Banana");
// 再次迭代元素(迭代器是强一致的)
for (String fruit : list) {
System.out.println(fruit);
}
}
}
Vector
和 CopyOnWriteArrayList区别
Vector
使用synchronized进行串行操作,极大降低了吞吐量
CopyOnWriteArrayList使用创建副本的方式,并发操作上去了,但是读操作使内存耗多了
-
线程安全性:
Vector
使用同步机制(如synchronized
)来实现线程安全,而CopyOnWriteArrayList
则使用一种称为 "写时复制"(Copy-On-Write)的机制来实现线程安全。在CopyOnWriteArrayList
中,当对集合进行修改操作时,会创建一个新的副本,修改操作在新的副本上进行,从而保证原有集合的线程安全性。这意味着读操作不会受到写操作的影响,读操作不需要加锁,因此读操作的性能较高。 -
性能:由于
CopyOnWriteArrayList
使用了写时复制的机制,它适用于读操作远远多于写操作的场景。当写操作频繁时,由于需要创建副本,会产生较高的内存开销。相比之下,Vector
在读写操作上都使用了同步机制,因此在写操作上的性能相对较低。如果应用程序中的写操作较多,CopyOnWriteArrayList
的性能可能会更好。 -
迭代器:
Vector
的迭代器是弱一致的,即在迭代期间允许其他线程对集合进行修改,但不保证迭代器能够反映出这些修改。而CopyOnWriteArrayList
的迭代器是强一致的,即在创建迭代器后,迭代器不会受到其他线程的修改影响,保证了迭代器的一致性。
综上所述,如果你需要在多线程环境下进行读操作远远多于写操作,并且对实时性要求不高,可以考虑使用 CopyOnWriteArrayList
。如果你需要在多线程环境下进行大量的读写操作,并且实时性较为重要,可以选择使用 Vector
。另外,如果你的应用程序对迭代器的一致性有更高的要求,可以选择 CopyOnWriteArrayList
。