Java源码-ArrayList

ArrayList底层原理:
  • 1.ArrayList初始化为一个空数组
  • 2.ArrayList的Add操作不是线程安全的
  • 3.ArrayList添加第一个元素时,数组的容量设置为10
  • 4.当ArrayList数组超过当前容量时,扩容至1.5倍(遇到计算结果为小数的,向下取整),第一次扩容后,容量为15,第二次扩容至22...
  • 5.ArrayList在第一次和扩容后都会对数组进行拷贝,调用Arrays.copyOf方法。
 
单线程与多线程对比:
1.单线程安全,多线程不安全
2.如何解决
  • 1.用Vector代替ArrayList
    关于vector
      •  初始化容量为10
      •  add操作加了synchronized关键字,线程安全
      •  扩容时是扩充至2倍
      •  加了排斥锁增加安全性,但是会造成阻塞,性能较差
  • 2.用Collections.synchronized(new ArrayList<>())
    源码解析:
                ad因为Collections.synchronizedList封装后的list,list的所有操作方法都带锁关键字,                   所以线程安全
  • 3.CopyOnWriteArrayList
    copyOnWrite思想:
      • Copy on write:通过写时复制保证线程安全,一种读写分离的思想。
      • 写操作:添加元素时,不直接往当前容器添加,而是先拷贝一份数组,在新的数组中添加元素后,在将原容器的引用指向新的容器。因为数组时用volatile关键字修饰的,所以当array重新赋值后,其他线程可以立即知道(volatile的可见性)
      • 读操作:读取数组时,读老的数组,不需要加锁。
      • 读写分离:写操作是copy了一份新的数组进行写,读操作是读老的数组,所以是读写分离。
    add的流程:
      • 先定义了一个可重入锁 ReentrantLock
      • 添加元素前,先获取锁lock.lock()
      • 添加元素时,先拷贝当前数组 Arrays.copyOf
      • 添加元素时,扩容+1(len + 1)
      • 添加元素后,将数组引用指向新加了元素后的数组setArray(newElements)
posted @ 2020-09-02 15:26  空指针终结者  阅读(173)  评论(0)    收藏  举报