在Java中,哪些List实现是线程安全的?

在 Java 中,默认的 List 实现类(如 ArrayListLinkedList不是线程安全的。如果在多线程环境中使用这些 List 实现类,需要显式地加锁或使用线程安全的替代方案。以下是线程安全的 List 实现:


1. 线程安全的 List 实现

1.1 Vector

  • 线程安全性VectorList 的一个线程安全实现,其所有方法都使用 synchronized 进行同步。
  • 缺点:
    • 由于每个方法都进行同步,性能较低。
    • Java 1.2 引入了更好的集合类(如 ArrayList),因此 Vector 已被逐渐淘汰,不推荐使用。

示例

Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
System.out.println(vector); // 输出:[A, B]

1.2 CopyOnWriteArrayList

  • 线程安全性:CopyOnWriteArrayList是 List的线程安全实现,适用于多线程环境。它使用了一种 “写时复制”的机制:
    • 读操作不会加锁,非常高效。
    • 写操作(如 addset)会复制底层数组,因此写操作性能较低。
  • 适用场景:
    • 读多写少的场景,例如配置管理或事件监听器列表。
    • 频繁迭代且迭代期间不需要实时反映修改。

示例

import java.util.concurrent.CopyOnWriteArrayList;

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
System.out.println(list); // 输出:[A, B]

2. 非线程安全 List 的线程安全化

2.1 使用 Collections.synchronizedList()

  • 作用:将非线程安全的 List 包装成线程安全的 List
  • 内部机制synchronizedList 方法返回的 List 在每次访问时都会加锁,确保线程安全。
  • 注意事项:
    • 如果需要遍历 synchronizedList,必须手动同步,以避免并发修改异常。

示例

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("A");
list.add("B");

synchronized (list) { // 遍历时必须手动同步
    for (String item : list) {
        System.out.println(item);
    }
}

3. 线程安全 List 的实现方式对比

实现 线程安全性 性能 适用场景
Vector 所有方法同步 写性能较低,读性能一般 不推荐使用,已被淘汰
CopyOnWriteArrayList 线程安全(写时复制) 读性能高,写性能较低 读多写少的场景,例如缓存、配置等
Collections.synchronizedList 包装同步的 List 写性能较低,读性能一般 通用场景,适用于轻量级线程安全需求

4. 推荐使用的线程安全 List

选择建议:

  1. 如果是读多写少的场景,推荐使用 CopyOnWriteArrayList
  2. 如果需要通用的线程安全 List,可以使用 Collections.synchronizedList()
  3. 不建议使用 Vector,因为它是过时的设计,性能不如现代的集合类。

5. 示例:多线程环境中使用线程安全 List

使用 CopyOnWriteArrayList

import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafeListExample {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        // 添加数据
        list.add("A");
        list.add("B");

        // 启动多线程
        Thread t1 = new Thread(() -> list.add("C"));
        Thread t2 = new Thread(() -> System.out.println(list));

        t1.start();
        t2.start();
    }
}

使用 Collections.synchronizedList

import java.util.*;

public class ThreadSafeListExample {
    public static void main(String[] args) {
        List<String> list = Collections.synchronizedList(new ArrayList<>());

        // 添加数据
        list.add("A");
        list.add("B");

        // 遍历时加锁
        synchronized (list) {
            for (String item : list) {
                System.out.println(item);
            }
        }
    }
}

6. 总结

实现方式 优点 缺点
Vector 内置线程安全支持,简单易用 性能较低,已过时,不推荐使用
CopyOnWriteArrayList 读性能高,适合读多写少场景 写操作会复制数组,写性能较低
Collections.synchronizedList 简单易用,通用性强 读写都需要同步,性能一般

发表评论

后才能评论