首页 > 其他分享 >多线程(34)CopyOnWriteArrayList

多线程(34)CopyOnWriteArrayList

时间:2024-04-06 09:00:24浏览次数:17  
标签:Thread Object 34 CopyOnWriteArrayList 数组 操作 多线程 es

CopyOnWriteArrayList 是 Java 中一个线程安全的 ArrayList 变体,属于 java.util.concurrent 包。它通过在所有修改操作(如 add, set 等)上执行显式复制来实现线程安全。这种设计适用于列表读操作的数量远远大于写操作的场景。

设计原理

CopyOnWriteArrayList 的基本思想是,每当我们要修改列表的时候(添加、删除、设置等),不直接在当前的数组上进行操作,而是先将当前数组复制一份,然后在这个副本上进行修改。修改完成后,再将原来的数组引用指向新数组。这样做的好处是可以避免修改时阻塞读操作,读操作可以安全地访问数组,不需要加锁,因为对它们来说,数组从不改变。

结构解析

CopyOnWriteArrayList 内部维护了一个 volatile 的数组用来存储数据。由于使用了 volatile 关键字,它保证了数组内容的可见性。以下是一个简化的 CopyOnWriteArrayList 类的源码结构(基于 Java 8+),展示了其基本实现:

// CopyOnWriteArrayList 源码片段(简化版本,基于 Java 8+)
class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
    // 确保可见性和禁止指令重排序
    private transient volatile Object[] array;

    // 获取底层数组的方法
    final Object[] getArray() {
        return array;
    }

    // 将数组设置为提供的数组
    final void setArray(Object[] a) {
        array = a;
    }

    // 添加元素的方法
    public boolean add(E e) {
        // 加锁以确保线程安全
        synchronized (this) {
            Object[] es = getArray();
            int len = es.length;
            // 复制出一个新数组
            es = Arrays.copyOf(es, len + 1);
            // 在新数组上操作
            es[len] = e;
            // 将原数组引用指向新数组
            setArray(es);
            return true;
        }
    }

    // 其他方法省略...
}

代码演示

下面是一个使用 CopyOnWriteArrayList 的简单示例:

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListDemo {
    public static void main(String[] args) {
        CopyOnWriteArrayList<Integer> cowArrayList = new CopyOnWriteArrayList<>();

        // 示例:并发添加
        Thread thread1 = new Thread(() -> cowArrayList.add(1));
        Thread thread2 = new Thread(() -> cowArrayList.add(2));

        thread1.start();
        thread2.start();

        // 等待线程结束
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 迭代并打印结果
        for (Integer i : cowArrayList) {
            System.out.println(i);
        }
    }
}

总结

CopyOnWriteArrayList 提供了一种避免读写冲突的方法,非常适合读多写少的并发场景。它的优势是在进行遍历操作时不需要锁定,因此可以提高遍历操作的并发性能。但是,由于每次修改都需要复制整个底层数组,所以写操作的成本相对较高,特别是对于数据量大的列表。在选择使用 CopyOnWriteArrayList 之前,需要确保它适合你的应用场景。

标签:Thread,Object,34,CopyOnWriteArrayList,数组,操作,多线程,es
From: https://blog.csdn.net/qq_43012298/article/details/136766827

相关文章

  • [题解]ABC346 补题C~E
    想起上次的ABC346没打,刚才虚拟参赛打了A~D,E题思路有,但是实现方式没选好导致WA了,没能在赛时做出来。写下题解记录一下~C-Σ用求和公式先把\(1\simk\)的和求出来:\(\frac{k(k+1)}{2}\),然后对于\(A\)数组中的元素依次减去就行(注意相同元素不能减\(2\)次)点击查看代码#include<b......
  • C#-多线程
    线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。线程是**轻量级进程**。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了C......
  • 【Java EE】多线程(一)
    ......
  • 2-34. 绘制房子和可以被砍伐的树
    绘制房子首先将房子的下半部分绘制到GroupTop这层然后把房顶绘制到Front1这层绘制碰撞层可以被砍伐的树其中Tree01_Bottom是有阴影的树根,Tree01_Trunk是没有阴影的树根调整树根的锚点接着把树的上部分连接上去把树根和树干放到同一个父物体下面树遮挡人......
  • easyExcel通用导出(非注解,多线程)
    1、基础类描述ExcelWriter(导出工具类)Query(通用查询)Consumer(函数参数)SpringBeanUtil(获取bean)2、代码ExcelWriterimportcn.hutool.core.collection.CollUtil;importcn.hutool.core.collection.ListUtil;importcn.hutool.core.util.PageUtil;importcn.hutool.core.u......
  • AT-abc347(C,D)
    AtCoderBeginnerContest347C-IdealHolidays这场做得最头疼的题分析容易想到先用$(d_i+a+b-1)%(a+b)+1$把$d_i$映射到$[1,a+b]$的区间再排序,但由于未知星期一是哪天,我们也无法确定映射后的$d_i$是星期几关于这个映射可以自己推一下我们取a+b=7看几个例子对于32......
  • ABC347
    Alink很简单遍历,判断模\(k\)是否为\(0\),如果为\(0\),输出\(a_i/k\)。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,k;inta[105];signedmain(){ cin>>n>>k; for(inti=1;i<=n;++i){ cin>>a[i]; if(a[i]%......
  • 【WPF应用34】WPF基本控件-Menu的详解与示例
    WPF(WindowsPresentationFoundation)是.NET框架的一个部分,用于构建桌面应用程序的用户界面。在WPF中,菜单(Menu)是一种常用的控件,用于提供一组选项或命令,使用户可以根据自己的需要执行特定的操作。本文将详细介绍WPF中的Menu控件,包括其基本用法、属性和事件。同时,我们将通过一......
  • Java:多线程-继承Thread类
    在Java中,通过继承Thread类是实现多线程的一种方式。这种方式允许你创建自己的线程类,并定义线程执行的具体内容。以下是关于继承Thread类的详细讲解:继承Thread类的步骤创建线程类:创建一个继承自Thread的子类。重写run方法:在子类中重写run方法,定义线程执行的任务。run方法是......
  • Java:多线程相关知识概念
    Java中的多线程是指在单个程序中并行执行多个线程(即执行路径或任务)的能力。多线程在Java中是一个核心概念,它允许应用程序更有效地利用CPU资源,同时还能进行并发操作。以下是Java中多线程相关的详细知识:线程的基本概念线程(Thread):是操作系统能够进行运算调度的最小单位。它......