MST
星途 面试题库

面试题:Java Collections框架中不同线程安全集合类的性能对比及应用场景

请详细对比`Vector`、`Collections.synchronizedList`创建的线程安全列表以及`CopyOnWriteArrayList`在多线程环境下的性能表现,包括读操作、写操作等方面。并举例说明在何种具体应用场景下应优先选择使用哪种线程安全集合类。
46.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

读操作性能

  1. Vector:读操作时需要获取锁,这会导致在多线程环境下,如果有其他线程正在进行写操作,读操作会被阻塞,性能相对较低。因为锁的存在限制了并发读的能力。
  2. Collections.synchronizedList:与Vector类似,读操作也需要获取锁。当有多个线程同时读取时,同样会因为锁竞争而降低性能,在高并发读场景下表现不佳。
  3. CopyOnWriteArrayList:读操作不需要加锁。因为它是基于数组的复制,读操作直接读取原数组,不会影响写操作,所以读操作性能非常高,特别适合读多写少的场景。

写操作性能

  1. Vector:写操作(如addremove等)需要获取锁,在多线程环境下,锁的竞争会导致写操作的性能瓶颈。如果有大量的写操作,线程等待锁的时间会增加,整体性能下降。
  2. Collections.synchronizedList:同Vector,写操作加锁,多线程下锁竞争会影响性能,大量写操作时效率较低。
  3. CopyOnWriteArrayList:写操作(如addremove)时会复制一份新的数组,然后在新数组上进行操作,最后将原数组引用指向新数组。由于复制数组的开销较大,写操作性能相对较低,尤其是在数据量较大时。

应用场景

  1. Vector:适用于早期Java版本(JDK 1.0就存在),对线程安全集合需求简单,并且读写操作频率相对均衡的场景。不过由于其性能问题,现在较少使用。
  2. Collections.synchronizedList:适用于对已有List进行快速线程安全包装的场景,当读写操作频率较为均衡且并发量不是特别高时可以使用。例如,在一些遗留代码改造中,需要快速将普通List变为线程安全的场景。
  3. CopyOnWriteArrayList:适用于读多写少的场景,比如系统配置信息的存储、日志记录等。例如,一个应用程序需要频繁读取配置信息,但很少修改配置,就可以使用CopyOnWriteArrayList来存储配置项。

示例代码

  1. Vector
import java.util.Vector;

public class VectorExample {
    public static void main(String[] args) {
        Vector<Integer> vector = new Vector<>();
        vector.add(1);
        vector.add(2);
        // 读操作
        int value = vector.get(0);
        // 写操作
        vector.add(3);
    }
}
  1. Collections.synchronizedList
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SynchronizedListExample {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        List<Integer> synchronizedList = Collections.synchronizedList(list);
        synchronizedList.add(1);
        synchronizedList.add(2);
        // 读操作
        int value = synchronizedList.get(0);
        // 写操作
        synchronizedList.add(3);
    }
}
  1. CopyOnWriteArrayList
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<>();
        cowList.add(1);
        cowList.add(2);
        // 读操作
        int value = cowList.get(0);
        // 写操作
        cowList.add(3);
    }
}