zoukankan      html  css  js  c++  java
  • 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 的实现原理是一致的;

  • 相关阅读:
    相似数据检测算法
    从一个简单的程序中你能看到什么?(面向对象的真帝)
    如何更好的理解类和结构
    从一个很简单的文件上传来品味面向对象的大局观(抽象类和功能类)
    网站中的缩略图是如何生成的?(C#处理图像)
    进程间通信(一)
    POSIX线程-(六)
    进程间通信(四)
    进程间通信(三)
    POSIX线程-(五)
  • 原文地址:https://www.cnblogs.com/beppezhang/p/11214532.html
Copyright © 2011-2022 走看看