在Java中,哪些List实现是线程安全的?
在 Java 中,默认的 List
实现类(如 ArrayList
和 LinkedList
)不是线程安全的。如果在多线程环境中使用这些 List
实现类,需要显式地加锁或使用线程安全的替代方案。以下是线程安全的 List
实现:
1. 线程安全的 List
实现
1.1 Vector
- 线程安全性:
Vector
是List
的一个线程安全实现,其所有方法都使用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的线程安全实现,适用于多线程环境。它使用了一种 “写时复制”的机制:
- 读操作不会加锁,非常高效。
- 写操作(如
add
、set
)会复制底层数组,因此写操作性能较低。
- 适用场景:
- 读多写少的场景,例如配置管理或事件监听器列表。
- 频繁迭代且迭代期间不需要实时反映修改。
示例:
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
选择建议:
- 如果是读多写少的场景,推荐使用
CopyOnWriteArrayList
。 - 如果需要通用的线程安全
List
,可以使用Collections.synchronizedList()
。 - 不建议使用
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 |
简单易用,通用性强 | 读写都需要同步,性能一般 |