实用指南站
霓虹主题四 · 更硬核的阅读氛围

线程安全的ArrayList怎么做(详细解析)

发布时间:2025-12-13 12:04:55 阅读:315 次

在开发多ref="/tag/413/" style="color:#C468A7;font-weight:bold;">线程程序时,经常会遇到多个线程同时操作同一个集合的情况。比如一个打印任务调度系统,多个线程往任务队列里添加待打印的文件,这时候如果用普通的 ArrayList,很容易出现数据错乱甚至程序崩溃。

ArrayList 本身不是线程安全的,多个线程同时 add 或 get 的时候,可能触发并发修改异常(ConcurrentModificationException),或者读到不一致的数据。那怎么解决?

使用 Collections.synchronizedList

最简单的方式是用工具类包装一下:

import java.util.*;

List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("打印合同");
list.add("打印简历");

这样得到的 list 是线程安全的,但要注意:遍历时仍需手动同步:

synchronized (list) {
    for (String task : list) {
        System.out.println("正在处理:" + task);
    }
}

使用 CopyOnWriteArrayList

这是专门用于并发场景的 List 实现,适合读多写少的场合。比如打印系统的监控界面要频繁读取当前任务列表,但新增任务的频率不高。

import java.util.concurrent.CopyOnWriteArrayList;

CopyOnWriteArrayList<String> tasks = new CopyOnWriteArrayList<>();
tasks.add("打印发票");
tasks.add("打印清单");

for (String task : tasks) {
    System.out.println(task); // 无需加锁
}

它的原理是每次修改都创建新副本,读操作完全无锁,效率高,但频繁写会消耗内存和性能。

使用 Vector(不推荐)

Vector 是老式的线程安全集合,所有方法都加了 synchronized,性能较差,现在基本不用了。

如果你在做一个小型局域网打印共享程序,多个用户提交任务,建议直接上 CopyOnWriteArrayList,代码简洁又不容易出错。要是写的是高性能后台服务,对写操作要求高,可以考虑配合 synchronized 块使用普通 ArrayList 或转用其他并发结构。