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前后分两次拷贝至新数组。

  • 相关阅读:
    努力学习吧!
    C# 捕捉键盘事件
    oracle 11g 及 plsqldeveloper 相关操作
    Oracle 建表空间
    窗体程序 防止重复打开子窗体
    asp 下 ewebeditor 上传图片功能,在IE7,IE8 及更高版本上失效解决方法
    StringBuilder 在后台动态输出 html 代码
    起动停止 Oracle11g 三个服务的批处理写法
    MySQL 常用命令语句
    虚拟机—pychrm
  • 原文地址:https://www.cnblogs.com/shine_cn/p/4226922.html
Copyright © 2011-2022 走看看