导读:本期聚焦于小伙伴创作的《在Java中如何使用CopyOnWriteArrayList实现线程安全列表》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《在Java中如何使用CopyOnWriteArrayList实现线程安全列表》有用,将其分享出去将是对创作者最好的鼓励。

CopyOnWriteArrayList是java.util.concurrent包下的一个线程安全列表实现,它的核心设计思路是写时复制,也就是当对列表进行修改操作时,会先复制一份底层数组,在副本上完成修改后再将底层数组引用指向新的数组,从而保证读操作不需要加锁,读性能较高。

在Java中如何使用CopyOnWriteArrayList实现线程安全列表

CopyOnWriteArrayList的核心原理

CopyOnWriteArrayList的底层维护了一个volatile修饰的数组,所有读操作都是直接访问这个数组,不需要任何同步措施。写操作则需要通过内部的重入锁保证同一时间只有一个线程可以执行修改逻辑,修改时会创建新的数组,将原数组内容复制过去,再添加或修改元素,最后替换原数组引用。

这种设计的好处是读操作完全无锁,性能很高,但写操作因为需要复制数组,开销相对较大,所以更适合读多写少的并发场景。

常用操作方法

创建实例

可以通过以下方式创建CopyOnWriteArrayList实例:

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Arrays;

public class COWListDemo {
    public static void main(String[] args) {
        // 创建空列表
        CopyOnWriteArrayList<String> list1 = new CopyOnWriteArrayList<>();
        // 基于已有集合创建列表
        CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));
    }
}

添加元素

添加元素的方法和普通List类似,支持add、addAll等操作:

CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
// 添加单个元素
list.add(1);
list.add(2);
// 在指定位置插入元素
list.add(1, 10);
// 批量添加元素
list.addAll(Arrays.asList(3, 4, 5));

读取与修改元素

读取元素可以直接通过get方法,修改元素可以使用set方法:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));
// 读取元素
String first = list.get(0);
// 修改指定位置元素
list.set(1, "bb");

删除元素

删除操作支持按索引删除、按元素删除等方式:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c", "b"));
// 按索引删除
list.remove(0);
// 按元素删除第一个匹配项
list.remove("b");
// 批量删除
list.removeAll(Arrays.asList("c"));

遍历操作

CopyOnWriteArrayList的迭代器是弱一致性的,迭代器创建时会基于当时的数组快照进行遍历,后续对列表的修改不会影响已经创建的迭代器:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));
// 使用迭代器遍历
for (String item : list) {
    System.out.println(item);
}
// 使用forEach遍历
list.forEach(System.out::println);

适用场景与注意事项

适用场景

  • 读操作频率远高于写操作的并发场景,比如缓存列表、配置项列表等。
  • 需要遍历操作的同时允许其他线程修改列表的场景,因为迭代器基于快照,不会出现ConcurrentModificationException。

注意事项

  • 写操作开销大,因为每次修改都要复制整个数组,如果列表元素数量很多,写操作的性能会很差,不适合写频繁的场景。
  • 内存占用问题,写操作时会有新旧两个数组同时存在,可能导致内存占用升高,需要评估内存情况。
  • 数据一致性是最终一致性,读操作可能读到旧的数据,因为写操作完成后新数组才会被其他线程可见,不适合对数据实时性要求极高的场景。
  • 不要在遍历过程中对CopyOnWriteArrayList做修改操作,虽然不会抛异常,但修改不会反映到当前迭代器中,容易造成逻辑误解。

与普通ArrayList的对比

可以通过以下表格直观对比两者的差异:

对比项ArrayListCopyOnWriteArrayList
线程安全非线程安全线程安全
读操作性能无锁,性能好无锁,性能好
写操作性能无额外开销,性能好需要复制数组,开销大
遍历时修改会抛ConcurrentModificationException不会抛异常,基于快照遍历
适用场景单线程或外部加锁的场景读多写少的并发场景

实践示例:多线程场景下的安全列表操作

下面是一个简单的多线程读写示例,展示CopyOnWriteArrayList在并发场景下的表现:

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class COWListConcurrentDemo {
    public static void main(String[] args) throws InterruptedException {
        CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
        ExecutorService pool = Executors.newFixedThreadPool(5);
        // 启动3个写线程
        for (int i = 0; i < 3; i++) {
            int threadId = i;
            pool.submit(() -> {
                for (int j = 0; j < 5; j++) {
                    list.add(threadId * 10 + j);
                    System.out.println("线程" + threadId + "添加元素:" + (threadId * 10 + j));
                }
            });
        }
        // 启动2个读线程
        for (int i = 0; i < 2; i++) {
            int threadId = i;
            pool.submit(() -> {
                for (int j = 0; j < 10; j++) {
                    System.out.println("线程" + threadId + "读取列表大小:" + list.size());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
        }
        pool.shutdown();
    }
}

运行上述代码可以看到,多个线程同时读写CopyOnWriteArrayList时不会出现数据错乱或者异常,读线程可以正常获取到列表的最新大小,写线程的添加操作也都生效。

CopyOnWriteArrayListJava线程安全并发编程列表操作修改时间:2026-07-22 17:06:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。