问:Vector和ArrayList、LinkedList区别?别离的应用场景?
区别
Vector: 底层是数组实现,线程平安的,操作的时候应用synchronized进行加锁.ArrayList:底层是数组实现,线程不平安,查问和批改十分快,然而减少和删除慢.LinkedList: 底层是双向链表,线程不平安,查问和批改速度慢,然而减少和删除速度快.
应用场景
减少和删除场景多则用LinkedList查问和批改多则用ArrayListVector曾经很少用了
如果须要保障线程平安,ArrayList应该怎么做,用有几种形式?
罕用形式是两种,如果你说你本人写一个arrayList保障线程平安,那就是三种
形式一:应用synchronized加锁Collections.synchronizedList(new ArrayList<>()); 形式二:应用ReentrantLock加锁CopyOnWriteArrayList<>()
==死记硬背必定是不容易记住,咱们一起浏览一下源码吧==
synchronizedList的读写等办法全副都有synchronized关键字
// 读写操作都有锁public E get(int index) {synchronized (mutex) {return list.get(index);}}public E set(int index, E element) {synchronized (mutex) {return list.set(index, element);}}public void add(int index, E element) {synchronized (mutex) {list.add(index, element);}}public E remove(int index) {synchronized (mutex) {return list.remove(index);}}
CopyOnWriteArrayList用的是ReentrantLock形式加锁
public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true;} finally { lock.unlock();}}public E remove(int index) {final ReentrantLock lock = this.lock;lock.lock();try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(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 oldValue;} finally { lock.unlock();}}// 读操作没有锁public E get(int index) {return get(getArray(), index);}// 写操作有锁public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try { Object[] elements = getArray(); E oldValue = get(elements, index); if (oldValue != element) { int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } return oldValue;} finally { lock.unlock();}}
CopyOnWriteArrayList和Collections.synchronizedList实现线程平安有什么区别?
- 追溯上述的源码-CopyOnWriteArrayList:执行批改操作时,会拷贝一份新的数组进行操作「Arrays.copyOf()」,空间占用量大,浪费资源,代价低廉,源码外面用ReentrantLock可重入锁来保障不会有多个线程同时拷贝一份数组
追溯上述的源码-Collections.synchronizedList:线程平安的起因是因为它简直在每个办法中都应用了synchronized同步锁
CopyOnWriteArrayList和Collections.synchronizedList应用场景
- CopyOnWriteArrayList场景:读高性能,实用读操作远远大于写操作的场景中应用(读的时候是不须要加锁的,间接获取,删除和减少是须要加锁的,读多写少)
synchronizedList:写操作性能比CopyOnWriteArrayList好,读操作性能并不如CopyOnWriteArrayList
CopyOnWriteArrayList的设计思维是怎么的,有什么毛病?
- 设计思维:读写拆散+最终统一
- 毛病:通过源码能够晓得,写操作复制「Arrays.copyOf()」,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象,内存占用问题突出,如果对象大则容易产生Yong GC和Full GC