• CopyOnWriteArraySet 源码分析


    CopyOnWriteArraySet  源码分析:

    1:数据结构:

    private final CopyOnWriteArrayList<E> al; 内部维护的是一个CopyOnWriteArrayList,所以CopyOnWriteArraySet的实现原理是通过CopyOnWriteArrayList的机制来实现的;

    2:构造方法:

    public CopyOnWriteArraySet() {

            al = new CopyOnWriteArrayList<E>();

    }

    创建一个空的CopyOnWriteArrayList集合,回到CopyOnWriteArrayList中,这个构造方法有两个作用:

       1):setArray(new Object[0]); 新建一个长度为0的Object数组,并且赋值给array变量;

       2):final transient ReentrantLock lock = new ReentrantLock();实例化一个独占锁对象;

    3:方法分析,这里主要分析 add  get remove  这几个常用的方法:

     1):addd方法源码分析:

    public boolean add(E e) {

            return al.addIfAbsent(e);

    }

    内部调用CopyOnWriteArrayList 的addIfAbsent方法;

    下面对addIfAbsent这个方法进行分析:

    public boolean addIfAbsent(E e) {   //e=”beppe”

            Object[] snapshot = getArray();  // snapshot= Object[0]

            return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :

                addIfAbsent(e, snapshot);

        }

    接下来分析indexOf(e, snapshot, 0, snapshot.length) 这个方法:

    private static int indexOf(Object o, Object[] elements,

                                   int index, int fence) { //o=”beppe” elements=Object[]

    index=0  fence=0

            if (o == null) {   //插入空值的场景

                for (int i = index; i < fence; i++)

                    if (elements[i] == null)  //如果集合中之前有 null 元素存在则返回 i

                        return i;

            } else {   //非空值插入场景

                for (int i = index; i < fence; i++)

                    if (o.equals(elements[i]))

                        return i;

            }

            return -1;

        }

    indexOf() 这个方法的作用是判断需要添加的元素在集合中是否存在,若存在则返回该元素的索引,主要用于去重使用;

    如果集合中没有重复元素,则返回-1;下面分析addIfAbsent(e, snapshot)这个方法

    集合add 首个元素为例:

    private boolean addIfAbsent(E e, Object[] snapshot) { //e=”beppe1”  snapshot=Object[0]

            final ReentrantLock lock = this.lock;

            lock.lock();   //获取独占锁

            try {

                Object[] current = getArray();  // current=Object[0],当线程并发写入时 获取最新的数组值,这里主要是为了获取最新的数组

                int len = current.length;  //len=0

                if (snapshot != current) {  //说明这里并发操作

                    // Optimize for lost race to another addXXX operation

                    int common = Math.min(snapshot.length, len);              

    for (int i = 0; i < common; i++)

                        if (current[i] != snapshot[i] && eq(e, current[i]))

                            return false;

                    if (indexOf(e, current, common, len) >= 0)

                            return false;

                }

                //对数组进行动态扩容  copy 当前数组到 新数组中

                Object[] newElements = Arrays.copyOf(current, len + 1);

    //将新元素赋值到新的数组中

                newElements[len] = e;

                setArray(newElements);

                return true;

            } finally {

                lock.unlock();   //解锁

            }

        }

    4:remove方法:

    public boolean remove(Object o) {

            return al.remove(o);   // al 是一个CopyOnWriteArrayList 对象,这里就是执行CopyOnWriteArrayList的remove方法

        }

    public boolean remove(Object o) {

            Object[] snapshot = getArray();

            int index = indexOf(o, snapshot, 0, snapshot.length);

            return (index < 0) ? false : remove(o, snapshot, index);

        }

    说明:CopyOnWriteArraySet 内部维护的是一个 CopyOnWriteArrayList 数据结构,其原理和CopyOnWriteArrayList 的实现原理是一致的;

  • 相关阅读:
    PL/SQL database character set(AL32UTF8) and Client character set(ZHS16GBK) are different
    pl sql 无法解析指定的连接标识符
    【转】几个常用的Oracle存储过程
    .NET 条件查询实现--类似网上商城宝贝搜索
    SQL Server 中大小写区分的处理
    .NET DataGrid 导出Excel 无分页
    C# 读书笔记之访问虚方法、重写方法和隐藏方法
    人工智能技术在中小学课堂中的应用
    dzzoffice协同办公平台与onlyoffice在线协作平台安装与部署
    一本通 确定进制
  • 原文地址:https://www.cnblogs.com/beppezhang/p/11214532.html
Copyright © 2020-2023  润新知