CopyOnWriteArrayList技术探究

简介: CopyOnWriteArrayList 是java.util.concurrent的并发类,线程安全,遵循写时复制的原则(CopyOnWrite)。通过“写入时复制”(Copy-On-Write, COW)的策略来保证集合的线程安全,适用于读多写少的并发场景。

工作原理

CopyOnWriteArrayList 是java.util.concurrent的并发类,线程安全,遵循写时复制的原则(CopyOnWrite)。通过“写入时复制”(Copy-On-Write, COW)的策略来保证集合的线程安全,适用于读多写少的并发场景。

CopyOnWriteArrayList 在每次修改操作时(如添加、删除、设置等),都会通过复制底层数组来创建一个新的数组,并在这个新数组上进行修改,然后将原数组的引用指向这个新数组。这样,在修改过程中,迭代器和其他分割器(spliterator)可以继续安全地遍历原数组,因为它们不会受到修改操作的影响。

优点

  1. 线程安全:通过内部机制保证了线程安全,无需外部同步。
  2. 读操作性能高:读操作不会加锁,且多个读操作可以并发执行,因此读操作的性能非常高。

缺点

  1. 内存占用高:每次修改操作都需要复制整个底层数组,这会导致大量的内存占用,特别是在数组较大且修改频繁时。
  2. 写操作性能低:写操作(添加、删除、设置等)涉及数组的复制,因此写操作相对较慢,且写操作的性能会随着数组容量的增加而下降。

使用场景

  • 读多写少的并发场景。
  • 遍历操作远多于修改操作的场景。
  • 在需要线程安全的列表,但又不想因为使用 Vector 而导致性能下降时。

示例代码

import java.util.concurrent.CopyOnWriteArrayList;  
  
public class CopyOnWriteArrayListExample {  
    public static void main(String[] args) {  
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();  
  
        // 线程1添加元素  
        Thread t1 = new Thread(() -> {  
            for (int i = 0; i < 10; i++) {  
                list.add("Element " + i);  
                try {  
                    Thread.sleep(100); // 模拟耗时操作  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        });  
  
        // 线程2遍历元素  
        Thread t2 = new Thread(() -> {  
            for (String s : list) {  
                System.out.println(s);  
            }  
        });  
  
        t1.start();  
        t2.start();  
  
        try {  
            t1.join();  
            t2.join();  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
}

image.gif

总结

CopyOnWriteArrayList的优势在于可以保证线程安全的同时,不阻塞读操作,但是这仅限于读多写少的情况,在写多读少的情况下,或者写入的对象占用内容较大时,不建议使用。

相关文章
|
存储 关系型数据库 MySQL
MySQL - 索引类型详解
MySQL - 索引类型详解
614 0
RecyclerView禁止复用
RecyclerView禁止复用
2459 0
|
人工智能 自然语言处理 数据挖掘
如何通过AI辅助数据分析
“数据驱动决策"已成为企业战略共识,越来越多的企业将数据分析列入核心投资。随着AI越来越成熟,使用AI辅助数据分析可以显著提升效率、深度和自动化水平。
1585 7
|
存储 Java 编译器
JNI内存方面说明以及相关类型手动释放内存
JNI内存方面说明以及相关类型手动释放内存
1773 0
|
弹性计算 搜索推荐 安全
如何编写有效的Prompt模板:提升大模型性能的关键
在大模型应用中,编写有效的Prompt至关重要。本文介绍了如何编写高质量的Prompt模板,包括明确任务定义、选择高质量示例、优化任务指示和调整示例顺序。详细探讨了百炼平台提供的三种主要Prompt模板(ICIO、CRISPE、RASCEF)及静态和动态样例库的创建与应用,帮助提升模型性能。
1434 0
|
安全 JavaScript
Vue3+Pinia实现Keycloak高效身份验证!
Vue3+Pinia实现Keycloak高效身份验证!
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之从MySQL到StarRocks的操作步骤是怎样的
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
机器学习/深度学习 数据采集 算法
基于Python实现随机森林分类模型(RandomForestClassifier)项目实战
基于Python实现随机森林分类模型(RandomForestClassifier)项目实战
|
Java Apache Maven
maven安装与zsh环境变量配置
maven安装与zsh环境变量配置
|
传感器 编解码 人工智能
pie engine——数字高程模型DEM/ALOS_DEM_12.5m数据集
pie engine——数字高程模型DEM/ALOS_DEM_12.5m数据集
777 0

热门文章

最新文章