一、ArrayList底层原理
1.特点及其原理:ArrayList底层基于数组实现,查找快,增删慢
2.ArrayList底层原理,初始化及调用add()方法添加元素:
默认初始化容量为10
第一次创建集合并在添加第一个元素时在底层创建一个默认长度为10的数组:
调用构造函数初始化时默认创建的是空数组
只有在调用add方法添加第一个元素时才会在底层创建默认长度为10的数组
总结:第一次创建集合并添加第一个元素时在底层创建一个默认长度为10的数组;当元素插满,会进行扩容,每次扩容到之前的1.5倍(oldCapacity + (oldCapacity >> 1,二进制右移即除二,左移乘二),如果扩容1.5倍之后容量还不够,则将所需要的最小容量minCapacity赋给数组新的容量值newCapacity;扩容之后通过数组的拷贝(使用Arrays.copyOf)来确保元素的准确性。
二、ArrayList线程安全问题
由上图add()方法可知,在ArrayList中的add方法没有做相关线程安全的处理,故ArrayList本身是线程不安全的,与之相关的线程安全的方法有:
1.Vector类
Vector和ArrayList语法相同,都继承了同一个类实现了相同的接口
Vector中的add()方法添加了synchronized关键字,故Vector类是线程安全的
但是由于Vector是直接在方法上使用synchronized锁住整个方法,并发效率低,在高并发的情况下容 易造成线程阻塞等问题。
2.使用Collections工具类
使用集合的工具类Collections提供的synchronizedList方法将线程不安全的集合类变为安全的
//将线程不安全的集合对象作为参数传入synchronizedXxx()方法中
List synchronizedList = Collections.synchronizedList(arrayList);
新new一个线程安全的SynchronizedRandomAccessList或SynchronizedList。当传入的 list 是ArrayList 时,返回 SynchronizedRandomAccessList 对象;传入 LinkedList 时,返回SynchronizedList 对象。(因为ArrayList实现了RandomAccess接口而 LinkedList 没有)
而SynchronizedRandomAccessList又继承了SynchronizedList,在调用SynchronizedRandomAccessList时构造器会调用super(list)即SynchronizedList类
可以看到SynchronizedList中的add、get、remove等方法内都加了mutex对象锁,从而实现线程安全。
与Vector比较,Vector直接锁住整个方法,而使用synchronizedList时锁住方法内部的部分代码,效率会高一点。
3.在大量并发情况下使用CopyOnWriteArrayList提高集合的效率和安全
使用Lock锁相较于Synchronized关键字更为灵活、效率更高;使用transient保证值被修改后,其它线程能够立马感知到最新值。且CopyOnWriteArrayList中只有写操作加了lock锁,而读操作(get方法)未加锁,从而提高读取效率(而synchronizedList和Vector中的get方法均加了synchronized关键字):
从 add ()方法中可以看出,CopyOnWriteArrayList 通过volatile、加锁 、 以及数组拷贝来保证了集合的线程安全。
总结:CopyOnWriteArrayList是一个读操作时无锁,写操作时使用volatile关键字、lock锁以及数组拷贝来保证线程安全的ArrayList。
三、ArrayList与相关集合的区别
1.ArrayList和LinkedList
-
ArrayList底层基于数组,LinkedList底层基于双链表
-
广泛上来说:ArrayList适合查询,LinkedList适合插入,但是如果获取的是第一个元素,或最后一个元素,LinkedList查询也很快,因为LinkedList中有两个属性分别记录了当前链表中的头结点和尾结点。
-
ArrayList实现了RandomAccess接口,以便在随机访问列表或顺序访问列表时提供良好的性能;而LinkedList没有实现该接口。
2.ArrayList和Vector
-
ArrayList同一时间允许多个线程进行访问,效率高、但是线程不安全,而Vector是线程安全的,但是效率低
-
ArrayList扩容是每次扩大到原来的1.5倍,Vector扩容是增加原来的两倍
-
ArrayList可使用集合工具类Collections的synchronizedList方法将线程不安全的ArrayList集合变为安全的,所以现在很少会使用到Vector