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 不會app
CopyOnWrite的含義ide
建立新副本、讀寫分離函數
不可變原理源碼分析
迭代的時候this
咱們看下ArrayList 源碼爲何會報錯spa
@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]; }
點開方法,他會進行一個比較操做因此會出現異常3d
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
咱們看下 CopyOnWriteArrayList 源碼code
這是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.yxl520.cn/