Vector 和 CopyOnWriteArrayList

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);
        }
    }
}

VectorCopyOnWriteArrayList区别

Vector 使用synchronized进行串行操作,极大降低了吞吐量

CopyOnWriteArrayList使用创建副本的方式,并发操作上去了,但是读操作使内存耗多了

  1. 线程安全性Vector 使用同步机制(如 synchronized)来实现线程安全,而 CopyOnWriteArrayList 则使用一种称为 "写时复制"(Copy-On-Write)的机制来实现线程安全。在 CopyOnWriteArrayList 中,当对集合进行修改操作时,会创建一个新的副本,修改操作在新的副本上进行,从而保证原有集合的线程安全性。这意味着读操作不会受到写操作的影响,读操作不需要加锁,因此读操作的性能较高。

  2. 性能:由于 CopyOnWriteArrayList 使用了写时复制的机制,它适用于读操作远远多于写操作的场景。当写操作频繁时,由于需要创建副本,会产生较高的内存开销。相比之下,Vector 在读写操作上都使用了同步机制,因此在写操作上的性能相对较低。如果应用程序中的写操作较多,CopyOnWriteArrayList 的性能可能会更好。

  3. 迭代器Vector 的迭代器是弱一致的,即在迭代期间允许其他线程对集合进行修改,但不保证迭代器能够反映出这些修改。而 CopyOnWriteArrayList 的迭代器是强一致的,即在创建迭代器后,迭代器不会受到其他线程的修改影响,保证了迭代器的一致性。

综上所述,如果你需要在多线程环境下进行读操作远远多于写操作,并且对实时性要求不高,可以考虑使用 CopyOnWriteArrayList。如果你需要在多线程环境下进行大量的读写操作,并且实时性较为重要,可以选择使用 Vector。另外,如果你的应用程序对迭代器的一致性有更高的要求,可以选择 CopyOnWriteArrayList

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值