ArrayList
public static void main(String[] args) { List list=new ArrayList(); list.add("11"); list.add("22"); list.add("33"); Iterator iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(list); Object next = iterator.next(); System.out.println(next); if(next.equals("11")){ list.remove("22"); } if(next.equals("33")){ list.add("2222"); } } }CopyOnWriteArrayList
public static void main(String[] args) { CopyOnWriteArrayList list = new CopyOnWriteArrayList(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); Iterator iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(list); Object next = iterator.next(); System.out.println(next); if (next.equals("11")) { list.remove("22"); } if (next.equals("33")) { list.add("2222"); } } }通过案例我们可以发现 ArrayList 迭代修改的时候会 抛出异常 ,而CopyOnWriteArrayList 不会
CopyOnWrite的含义
创建新副本、读写分离
不可变原理
迭代的时候
我们看下ArrayList 源码为什么会报错
@SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }点开方法,他会进行一个比较操作所以会出现异常
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }我们看下 CopyOnWriteArrayList 源码
这是CopyOnWriteArrayList存放数据的地方,只能通过getArray获取 并且他会上锁,用的ReentrantLock
/** The lock protecting all mutators */ final transient ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ private transient volatile Object[] array;初始化 :构造函数 新建个空的数组
/** * Sets the array. */ final void setArray(Object[] a) { array = a; } /** * Creates an empty list. */ public CopyOnWriteArrayList() { setArray(new Object[0]); }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(); //获取长度 //copy出一个新的数组 Object[] newElements = Arrays.copyOf(elements, len + 1); //将我们的参数添加到这个位置 newElements[len] = e; //set方法添加至 setArray(newElements); return true; } finally { //释放锁 lock.unlock(); } }get方法
@SuppressWarnings("unchecked") private E get(Object[] a, int index) { return (E) a[index]; } /** * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { return get(getArray(), index); } public boolean hasNext() { return cursor < snapshot.length; } public boolean hasPrevious() { return cursor > 0; } @SuppressWarnings("unchecked") public E next() { //判断 true 和 false //逻辑简单了许多 if (! hasNext()) throw new NoSuchElementException(); return (E) snapshot[cursor++]; }个人博客地址:http://blog.yanxiaolong.cn/