• CopyOnWriteArrayList&Collections.synchronizedList()


    1、ArrayList

      ArrayList是非线性安全,此类的 iterator() 和 listIterator() 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。即在一方在遍历列表,而另一方在修改列表时,会报ConcurrentModificationException错误。而这不是唯一的并发时容易发生的错误,在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据。

    2、CopyOnWriteArrayList

      CopyOnWriteArrayList的add和remove方法是同步的(防止多个线程写操作时出现多个副本),每次修改都会创建并发布一个副本,get方法则不是同步的。看以下源码。该类的add、remove方法不具备原子性,所以一个在写,另一个线程在读到的数据可能是修改前的数据。

    优点:多个线程可以同时对这个容器进行迭代,而不会相互干扰或者与修改容器的线程互相干扰,即不会抛出ConcurrentModificationException,并且返回的元素与迭代器创建时的元素完全一致,而不必考虑之后修改带来的影响。

    缺点:1、在添加元素时会创建副本,如果副本占用内较大,会增加gc,严重可能会影响相应时间。2、数据只能保证最终一致性,无法保证实时性,可能读到的还是老的数据。

    适用场景:适用于读多写少,并且对数据得一致性要求不高。

    3、Collections.synchronizedList()

    看看源码我们知道,Collections.synchronizedList()事实上是采用静态代理的方式进行操作,它的每个方法都是同步的,这样保证了列表操作都是线程安全的。相对于CopyOnWriteArrayList,Collections.synchronizedList()的在多个线程中写操作较快,读慢。

    4、CopyOnWriteArrayList和Collections.synchronizedList()代码实测。

    1)写

    public class Test {
        public static void main(String[] args) {
            List<String> list1 = new CopyOnWriteArrayList<String>();
            List<String> list2 = Collections.synchronizedList(new ArrayList<String>());
    
            int count = 100;
            long time1 = System.currentTimeMillis();
            while (System.currentTimeMillis() - time1 < count) {
                list1.add("1");
            }
            System.gc();
            long time2 = System.currentTimeMillis();
            while (System.currentTimeMillis() - time2 < count) {
                list2.add("1");
            }
            System.out.println("CopyOnWriteArrayList在" + count + "毫秒时间内添加元素个数为:  " + list1.size());
            System.out.println("Collections.synchronizedList()在" + count + "毫秒时间内添加元素个数为:  " + list2.size());
        }
    }

    执行结果:

    CopyOnWriteArrayList在100毫秒时间内添加元素个数为: 7987
    Collections.synchronizedList()在100毫秒时间内添加元素个数为: 3027757

  • 相关阅读:
    Jenkins权限控制-Role Strategy Plugin插件使用
    迁移一个仓库到新的Gitlab
    Gitlab备份以及恢复
    10.使用nexus3配置golang私有仓库
    9.使用nexus3配置Python私有仓库
    8.maven上传jar包以及SNAPSHOT的一个坑
    7.nexus版本升级
    6.使用nexus3配置yum私有仓库
    5.使用nexus3配置npm私有仓库
    4.maven私服nexus2迁移到nexus3
  • 原文地址:https://www.cnblogs.com/zhi-leaf/p/10549013.html
Copyright © 2020-2023  润新知