Java中很少用的CopyOnWriteArrayList

类注释

/**
 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
 * operations ({@code add}, {@code set}, and so on) are implemented by
 * making a fresh copy of the underlying array.
 * 一个线程安全的ArrayList变量, 其中所有的可变操作(如add, set...) 都会通过创建一个新的当前
 * 数组的拷贝
 *
 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
 * than alternatives when traversal operations vastly outnumber
 * mutations, and is useful when you cannot or don't want to
 * synchronize traversals, yet need to preclude interference among
 * concurrent threads.
 * 这通常代价过大, 但是当遍历操作远远超过变化时它会是更有效的, 当你不能或者不想执行同步遍历
 * 时, 你需要通对并发线程进行干预。
 * The "snapshot" style iterator method uses a reference to the state of the array  * at the point that the iterator was created.
 * 快照式的迭代方法在该迭代器被创建时使用了一个指向数组状态的引用。
 * This array never changes during the lifetime of the
 * iterator, so interference is impossible and the iterator is
 * guaranteed not to throw {@code ConcurrentModificationException}.
 * 该数组在此迭代器的生命周期中从未改变, 所以它不可能被干预, 并且此迭代确定不会抛出并发修改
 * 异常。
 *
 * The iterator will not reflect additions, removals, or changes to
 * the list since the iterator was created.
 * 只要迭代器的创建, 它就不会对此列表的添加, 移除, 改变作出反应。
 * Element-changing operations on iterators themselves ({@code remove}, {@code set},
 * and{@code add}) are not supported.
 * 会改变迭代器自身的元素改变操作不会被支持, 比如remove, set, add等
 * These methods throw {@code UnsupportedOperationException}.
 * 使用这些方法会抛出不支持的操作异常
 *
 * <p>All elements are permitted, including {@code null}.
 * 所有元素都是被允许的, 包括空
 * <p>Memory consistency effects: As with other concurrent
 * collections, actions in a thread prior to placing an object into a
 * {@code CopyOnWriteArrayList}
 * 内存一致性影响, 与其他并发集合相同, 线程中的行为优先于把对象放入CopyOnWriteArrayList中
 * <a href="package-summary.html#MemoryVisibility(内存可见性)"><i>happen-before</i>
 * </a>
 * actions subsequent to the access or removal of that element from
 * the {@code CopyOnWriteArrayList} in another thread.
 * 在从CopyOnWriteArrayList中获取或移除该元素之后的操作在其他线程中进行
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <E> the type of elements held in this collection
 */

属性

    private static final long serialVersionUID = 8673264195747942595L;

    /** The lock protecting all mutators
     * 保护所有突变因子的锁(可重入锁)
     * 注意: transient关键字标记的成员变量不参与序列化过程
     */
    final transient ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray.
     * 对象数组, 只能通过getArray/setArray获取
     */
    private transient volatile Object[] array;

方法

  • Constructor:

    • CopyOnWriteArrayList()

       /**
           * Creates an empty list.
           * 创建空列表
           */
          public CopyOnWriteArrayList() {
              setArray(new Object[0]);
          }
    • CopyOnWriteArrayList(Collection<? extends E> c)
      /**
           * Creates a list containing the elements of the specified
           * collection, in the order they are returned by the collection's
           * iterator.
           * 创建一个包含特定集合的元素的列表, 元素排序按集合的迭代器返回的顺序。
           *
           * @param c the collection of initially held elements
           * @throws NullPointerException if the specified collection is null
           */
          public CopyOnWriteArrayList(Collection<? extends E> c) {
              Object[] elements;
              // 如果集合c的类型是CopyOnWriteArrayList的类型
              if (c.getClass() == CopyOnWriteArrayList.class)
                  // 就获取数组
                  elements = ((CopyOnWriteArrayList<?>)c).getArray();
              else {
                  elements = c.toArray();
                  // c.toArray might (incorrectly) not return Object[] (see 6260652)
                  // c.toArray 可能不能正确地返回Object[](请查看issue 6260652)
                  // 如果元素数组类型不是Object数组类型
                  if (elements.getClass() != Object[].class)
                      // 就重新拷贝一份为Object数组类型的元素数组
                      elements = Arrays.copyOf(elements, elements.length, Object[].class);
              }
              setArray(elements);
          }
    • CopyOnWriteArrayList(E[] toCopyIn)
      /**
           * Creates a list holding a copy of the given array.
           * 将对象数组设置为获得的数组的拷贝
           *
           * @param toCopyIn the array (a copy of this array is used as the
           *        internal array)
           * @throws NullPointerException if the specified array is null
           */
          public CopyOnWriteArrayList(E[] toCopyIn) {
              setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
          }

      ```

    ```

  • 重要方法
    • set()

       /**
           * Replaces the element at the specified position in this list with the
           * specified element.
           * 替换列表中特定位置的元素为xx
           *
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public E set(int index, E element) {
              // 获取可重入锁
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  // 获取旧值
                  E oldValue = get(elements, index);
      
                  // 如果旧值与传入的元素不相等
                  if (oldValue != element) {
                      int len = elements.length;
                      // 拷贝一份新的元素数组
                      Object[] newElements = Arrays.copyOf(elements, len);
                      // 并将元素传入的元素赋给新的元素数组该位置的值
                      newElements[index] = element;
                      // 将新元素数组赋值给对象数组
                      setArray(newElements);
                  } else {
                      // Not quite a no-op; ensures volatile write semantics
                      // 并不是无操作, 需要确保写语义的可见性
                      setArray(elements);
                }
                  // 返回旧值
                return oldValue;
              } finally {
                  lock.unlock();
              }
          }
      
    • add()
      /**
           * Appends the specified element to the end of this list.
           * 将特定的元素添加到此列表尾部
           * @param e element to be appended to this list
           * @return {@code true} (as specified by {@link Collection#add})
           */
          public boolean add(E e) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  // 其实最主要的还是对原数组进行了拷贝
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                  newElements[len] = e;
                setArray(newElements);
                  return true;
            } finally {
                  lock.unlock();
              }
          }
      
    • add(int index, E element)
          /**
           * Inserts the specified element at the specified position in this
           * list.
           * 插入特定的元素到指定的位置
           * Shifts the element currently at that position (if any) and
           * any subsequent elements to the right (adds one to their indices).
           * 插入后将从该位置开始其后所有的元素的位置右移一位
           *
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public void add(int index, E element) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  // 如果越界就抛异常
                  if (index > len || index < 0)
                      throw new IndexOutOfBoundsException("Index: "+index+
                                                          ", Size: "+len);
                  Object[] newElements;
                  // 需要移动的数量
                  int numMoved = len - index;
                if (numMoved == 0)
                      // 如果就是在最后位置添加, 再拷一个长度+1的数组给赋给新元素数组
                    newElements = Arrays.copyOf(elements, len + 1);
                  else {
                    // 先扩位
                      newElements = new Object[len + 1];
                      // 再将旧元素数组中的值拷贝给新数组
                      System.arraycopy(elements, 0, newElements, 0, index);
                      // 再将从该位置开始其后所有的元素的位置右移一位
                      System.arraycopy(elements, index, newElements, index + 1,
                                       numMoved);
                  }
                  newElements[index] = element;
                  setArray(newElements);
              } finally {
                  lock.unlock();
              }
          }
    • E remove(int index)
          /**
           * Removes the element at the specified position in this list.
           * 移除指定位置的元素
           * Shifts any subsequent elements to the left (subtracts one from their
           * indices).
           * 将该位置后的元素前移
           * Returns the element that was removed from the list.
           * 返回从列表被移除的元素
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public E remove(int index) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                Object[] elements = getArray();
                  int len = elements.length;
                E oldValue = get(elements, index);
                  // 需要前移的元素数量
                  int numMoved = len - index - 1;
                if (numMoved == 0)
                      setArray(Arrays.copyOf(elements, len - 1));
                  else {
                      // 与之前同理
                      Object[] newElements = new Object[len - 1];
                      System.arraycopy(elements, 0, newElements, 0, index);
                      System.arraycopy(elements, index + 1, newElements, index,
                                       numMoved);
                      setArray(newElements);
                  }
                  return oldValue;
              } finally {
                  lock.unlock();
              }
          }
    • boolean remove(Object o)
      /**
         * Removes the first occurrence of the specified element from this list,
         * if it is present.
         * 移除列表中出现的第一个出现的该元素。
         * If this list does not contain the element, it is unchanged.
         * 如果没有该元素, 就不变
         * More formally, removes the element with the lowest index
         * 更正式地说, 移除参数位置最小的该元素
         * {@code i} such that
           * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
           * (if such an element exists).
           * Returns {@code true} if this list contained the specified element (or
           * equivalently, if this list changed as a result of the call).
           * 如果有该元素, 且对象数组被改变, 就返回true
           *
           * @param o element to be removed from this list, if present
           * @return {@code true} if this list contained the specified element
           */
          public boolean remove(Object o) {
              // 获取当前快照
              Object[] snapshot = getArray();
              int index = indexOf(o, snapshot, 0, snapshot.length);
              return (index < 0) ? false : remove(o, snapshot, index);
          }
    • boolean remove(Object o, Object[] snapshot, int index)
      /**
           * A version of remove(Object) using the strong hint that given
           * recent snapshot contains o at the given index.
           * 根据已得的包含位置为index的最近的快照, 使用强暗示进行移除?
           */
          private boolean remove(Object o, Object[] snapshot, int index) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] current = getArray();
                  int len = current.length;
                  // 如果快债不是当前快照(findIndex是一个标签, java保留goto部分作用还记得不, break跳转过来的)
                  if (snapshot != current) findIndex: {
                      // 获取前缀
                      int prefix = Math.min(index, len);
                      for (int i = 0; i < prefix; i++) {
                          if (current[i] != snapshot[i] && eq(o, current[i])) {
                              index = i;
                              break findIndex;
                          }
                      }
                      if (index >= len)
                        return false;
                      if (current[index] == o)
                        break findIndex;
                      index = indexOf(o, current, index, len);
                    if (index < 0)
                          return false;
                  }
                  Object[] newElements = new Object[len - 1];
                  System.arraycopy(current, 0, newElements, 0, index);
                  System.arraycopy(current, index + 1,
                                   newElements, index,
                                   len - index - 1);
                  setArray(newElements);
                  return true;
              } finally {
                  lock.unlock();
              }
          }
    • removeRange(int fromIndex, int toIndex) 移除哪个区域的元素
        /**
           * Removes from this list all of the elements whose index is between
           * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
           * Shifts any succeeding elements to the left (reduces their index).
           * This call shortens the list by {@code (toIndex - fromIndex)} elements.
           * (If {@code toIndex==fromIndex}, this operation has no effect.)
           *
           * @param fromIndex index of first element to be removed
           * @param toIndex index after last element to be removed
           * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
           *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
           */
          void removeRange(int fromIndex, int toIndex) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
      
                  if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
                    throw new IndexOutOfBoundsException();
                  int newlen = len - (toIndex - fromIndex);
                int numMoved = len - toIndex;
                  if (numMoved == 0)
                      setArray(Arrays.copyOf(elements, newlen));
                  else {
                      Object[] newElements = new Object[newlen];
                      System.arraycopy(elements, 0, newElements, 0, fromIndex);
                      System.arraycopy(elements, toIndex, newElements,
                                       fromIndex, numMoved);
                      setArray(newElements);
                  }
              } finally {
                  lock.unlock();
              }
          }
  • boolean addIfAbsent() 如果不存在就添加到最后
    /**
         * Appends the element, if not present.
         *
         * @param e element to be added to this list, if absent
         * @return {@code true} if the element was added
         */
        public boolean addIfAbsent(E e) {
            Object[] snapshot = getArray();
            return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
                addIfAbsent(e, snapshot);
        }
    • boolean addIfAbsent(E e, Object[] snapshot)

      /**
           * A version of addIfAbsent using the strong hint that given
           * recent snapshot does not contain e.
           * 一个使用了强按时(最近快照中没有e)
           */
          private boolean addIfAbsent(E e, Object[] snapshot) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] current = getArray();
                int len = current.length;
                  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;
                  }
                  Object[] newElements = Arrays.copyOf(current, len + 1);
                  newElements[len] = e;
                  setArray(newElements);
                  return true;
              } finally {
                  lock.unlock();
              }
          }
    • boolean containsAll(Collection<?> c): 包含所有
          /**
           * Returns {@code true} if this list contains all of the elements of the
           * specified collection.
           *
           * @param c collection to be checked for containment in this list
           * @return {@code true} if this list contains all of the elements of the
           *         specified collection
           * @throws NullPointerException if the specified collection is null
           * @see #contains(Object)
           */
          public boolean containsAll(Collection<?> c) {
              Object[] elements = getArray();
              int len = elements.length;
              for (Object e : c) {
                  if (indexOf(e, elements, 0, len) < 0)
                      return false;
              }
              return true;
          }
    • boolean removeAll(Collection<?> c): 移除所有
      /**
           * Removes from this list all of its elements that are contained in
           * the specified collection.
           * 在列表中移除所有集合中包含的元素
           * This is a particularly expensive operation
           * in this class because of the need for an internal temporary array.
           * 因为需要临时数组, 所以开销较大。
           *
           * @param c collection containing elements to be removed from this list
           * @return {@code true} if this list changed as a result of the call
           * @throws ClassCastException if the class of an element of this list
           *         is incompatible with the specified collection
           *         (<a href="../Collection.html#optional-restrictions">optional</a>)
           * @throws NullPointerException if this list contains a null element and the
           *         specified collection does not permit null elements
           *         (<a href="../Collection.html#optional-restrictions">optional</a>),
           *         or if the specified collection is null
           * @see #remove(Object)
           */
          public boolean removeAll(Collection<?> c) {
              if (c == null) throw new NullPointerException();
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  if (len != 0) {
                      // temp array holds those elements we know we want to keep
                      // 使用临时数组维护这些我们想要保留的元素
                      int newlen = 0;
                      Object[] temp = new Object[len];
                      for (int i = 0; i < len; ++i) {
                          Object element = elements[i];
                          if (!c.contains(element))
                              temp[newlen++] = element;
                      }
                      if (newlen != len) {
                          setArray(Arrays.copyOf(temp, newlen));
                          return true;
                      }
                  }
                  return false;
              } finally {
                  lock.unlock();
              }
          }
    • boolean retainAll(Collection<?> c)
      /**
           * Retains only the elements in this list that are contained in the
           * specified collection.
           * 在列表中保留所有该特定集合中含有的元素。
           *
           * In other words, removes from this list all of its elements that are
           * not contained in the specified collection.
           * 也就是会将所有不在该集合中的元素移除(说白了取交集)
           *
           * @param c collection containing elements to be retained in this list
           * @return {@code true} if this list changed as a result of the call
           * @throws ClassCastException if the class of an element of this list
           *         is incompatible with the specified collection
           *         (<a href="../Collection.html#optional-restrictions">optional</a>)
           * @throws NullPointerException if this list contains a null element and the
           *         specified collection does not permit null elements
           *         (<a href="../Collection.html#optional-restrictions">optional</a>),
           *         or if the specified collection is null
           * @see #remove(Object)
           */
          public boolean retainAll(Collection<?> c) {
              if (c == null) throw new NullPointerException();
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  if (len != 0) {
                      // temp array holds those elements we know we want to keep
                      // 使用临时数组维护这些我们想要保留的元素
                      int newlen = 0;
                      Object[] temp = new Object[len];
                      for (int i = 0; i < len; ++i) {
                          Object element = elements[i];
                          if (c.contains(element))
                              temp[newlen++] = element;
                      }
                      if (newlen != len) {
                          setArray(Arrays.copyOf(temp, newlen));
                          return true;
                      }
                  }
                  return false;
              } finally {
                  lock.unlock();
              }
          }

原文地址:https://www.cnblogs.com/ronnieyuan/p/12148280.html

时间: 2024-08-04 10:41:40

Java中很少用的CopyOnWriteArrayList的相关文章

为什么函数式编程在Java中很危险?

摘要:函数式编程这个不温不火的语言由来已久.有人说,这一年它会很火,尽管它很难,这也正是你需要学习的理由.那么,为什么函数式编程在Java中很危险呢?也许这个疑问普遍存在于很多程序员的脑中,作者Elliotte对此发表了一些见解,我们一起来看看他是怎么说的. 在我的日常工作中,我身边的开发者大多是毕业于CS编程顶级院校比如MIT.CMU以及Chicago,他们初次涉及的语言是Haskell.Scheme及Lisp.他们认为函数式编程是一种自然的.直观的.美丽的且高效的编程样式.但奇怪的是,我和我

Java 编程语言中很少被人了解的特性-statement label

下面的语句会编译报错或者打印什么? System.out.print("baidu site :"); https://www.baidu.com; System.out.println(" format"); 很多人会说:会编译出错,中间那行是什么鬼? 其实,不会报错,会打印出: baidu site : format 如果改成这样的语句,是不是就不会觉得编译报错了? System.out.print("baidu site :"); http

为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分,有没有放过自定义对象?而这个时候,候选人说放过,于是两个问题的回答就自相矛盾了. 最近问下来,这个问题普遍回答不大好,于是在本文里,就干脆从hash表讲起,讲述HashMap的存数据规则,由此大家就自然清楚上述问题的答案了. 1 通过Hash算法来了解HashMap对象的高效性 我们先复习数据结构里

Java 中很X的启动主键

生成工具:http://patorjk.com/software/taag/#p=testall&h=0&v=0&f=Graffiti&t=Type%20Something%20 如何修改spring boot 启动动画? 1.在resource 目录下创建 banner.txt 2.修改 banner.txt 内容 兔子 /*** * 瓦瓦 十 * 十齱龠己 亅瓦車己 * 乙龍龠毋日丶 丶乙己毋毋丶 * 十龠馬鬼車瓦 己十瓦毋毋 * 鬼馬龠馬龠十 己己毋車毋瓦 * 毋龠龠

java中你确定用对单例了吗?

作为程序猿这种特殊物种来说,都掌握了一种特殊能力就是编程思想,逻辑比较谨慎,但是有时候总会忽略到一些细节,比如我,一直以来总觉得Singleton是设计模式里最简单的,不用太在意,然而就是因为这种不在意在开发中吃亏了.真的too young to simple. 好不扯淡了,直入主题. 在代码的世界里发现有各种写法的单例,有人说单例有5种,6种,7种- 对于单例的分类这点必须规范下,首先这么多种的分类是根据什么来定义的,基准是什么?否则怎么会有那么多写法. 因此归纳下来,从延迟加载和执行效率的角

[Java类加载器]Java中classLoader浅析.

本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一.问题 请在Eclipse中新建如下类,并运行它: 1 package java.lang; 2 3 public class Long { 4 public static void main(String[] args) { 5 System.out.println("Hi, i am here"); 6 } 7 } 你能猜到它的运行如果吗? 不错,就是如下这个样子!

java 中的基本数据类型认识

Java是强类型语言,它的真正意思是我们在程序中写的任何数据都有类型,就算是写一个123,它也有类型.那它是什么类型呢?我们并没有对其进行类型声明啊?如果没有声明类型,那就采用默认类型.对于整数来说,默认类型为int, 小数的默认类型则是double. 字符类型为char等. 举一个例子,float f = 3.14; 程序就会报错.因为3.14是小数,默认类型是double, 而声明的变量f 是float 类型,我们正在把一个double类型的值赋值给一个float类型,而float类型的精度

JAVA中几个常用的方法

类Object是类层次结构的根类,每一个类都使用Object作为超类,所有对象(包括数组)都实现这个类的方法.jdk1.5中,描述了该类中的11个方法 1.getClass public final Class<? extends Object> getClass() 返回一个对象的运行时类.该 Class 对象是由所表示类的 static synchronized 方法锁定的对象. 返回: 表示该对象的运行时类的 java.lang.Class 对象.此结果属于类型 Class<? e

java中equals,hashcode和==的区别

1.== java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型 byte,short,char,int,long,float,double,boolean   他们之间的比较,应用双等号(==),比较的是他们的值. 2.引用类型(类.接口.数组) 当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false. 对象是放在堆中的,栈中存放的是对象的引用(地址).由此可见'=='是对栈中