问: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