zoukankan      html  css  js  c++  java
  • Java并发之CopyOnWriteArrayList

    CopyOnWriteArrayList是线程安全的、并且读操作无锁的ArrayList。
    不像ArrayList默认初始化大小为10的Object[],CopyOnWriteArrayList默认初始化大小为0的Object[]
    1,add(E)
    add方法没有给整个方法加synchronized关键字,而是使用ReentrantLock来保证线程安全。
    该方法和ArrayList的add方法不同,ArrayList在add时候如果List中元素个数超出Object[]大小,则扩容,默认扩容1.5倍,而CopyOnWriteArrayList是新创建一个比原来大1的数组,然后将新元素放在最后。

    2,remove(E)
    在ArrayList的remove方法中,代码如下:

    public E remove(int index) {
    ...
    E oldValue = (E) elementData[index];
    int numMoved = size - index - 1;
    if (numMoved > 0)
       System.arraycopy(elementData, index+1, elementData, index,
        numMoved);
    elementData[--size] = null; // Let gc do its work
    return oldValue;
    }


    从代码可以看出,ArrayList是直接操作原数组,利用 System.arraycopy将index之后的元素往前挪。
    而在CopyOnWriteArrayList的remove中,和add方法一样,也是通过ReentrantLock保证线程安全,代码如下:

    public E remove(int index) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
       Object[] elements = getArray();
       int len = elements.length;
       Object oldValue = 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 (E)oldValue;
    } finally {
       lock.unlock();
    }
        }
     


    从代码可以看出,CopyOnWriteArrayList新创建了一个大小比原来小1的新数组,然后利用System.arraycopy将原数组index前后分两次拷贝至新数组。

  • 相关阅读:
    Linq to OBJECT延时标准查询操作符
    LINQ to XML
    动态Linq(结合反射)
    HDU 1242 dFS 找目标最短路
    HDu1241 DFS搜索
    hdu 1224 最长路
    BOJ 2773 第K个与m互质的数
    ZOJ 2562 反素数
    2016 ccpc 杭州赛区的总结
    bfs UESTC 381 Knight and Rook
  • 原文地址:https://www.cnblogs.com/shine_cn/p/4226922.html
Copyright © 2011-2022 走看看