Q: What’s the difference between Vector and ArrayList or LinkedList? Separate usage scenarios?

  • The difference between

    Vector: The underlying implementation is an array, thread-safe, and synchronized locks are used during operations. ArrayList: At the bottom is the array implementation, which is thread unsafe and very fast for querying and modifying, but slow for adding and deleting. LinkedList: The bottom layer is bidirectional LinkedList, which is not safe for thread. It is slow to query and modify, but fast to add and delete.
  • Usage scenarios

    Adding and deleting scenes is mostly done with LinkedList queries and modifications are mostly done with ArrayList Vector which is rarely used anymore

    What should an ArrayList do if it needs to be thread-safe? In what ways?

  • There are two common ways. If you say you write an ArrayList yourself for thread-safety, there are three

    Way 1: using synchronized locking Collections. SynchronizedList (new ArrayList < > ()); CopyOnWriteArrayList<>()

    == rote memorization is certainly not easy to remember, let’s browse the source code ==

  • SynchronizedList methods all have the synchronized keyword

    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 uses ReentrantLock to lock

    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 and Collections. SynchronizedList realize thread safe and what’s the difference?

  • CopyOnWriteArrayList: When the modification operation is performed, it will copy a new array for the operation “Array.copyof ()”, which takes up a lot of space, is a waste of resources, and is expensive. ReentrantLock is used in the source code to ensure that there will not be multiple threads copy at the same time A batch of shellfish
  • Trace the source – the Collections. SynchronizedList: thread-safe because it almost in each method USES a synchronized synchronous lock

    CopyOnWriteArrayList and Collections. SynchronizedList usage scenario

  • CopyOnWriteArrayList scenario: read performance, suitable for the use of read operation is far greater than the write operation scenario (read is not required to lock, direct access, delete and add need to lock, read more than write less)
  • SynchronizedList: Write performance is better than CopyOnWriteArrayList, but read performance is not

    What is the design philosophy of CopyOnWriteArrayList, and what are its drawbacks?

  • Design idea: read/write separation + final consistency
  • Disadvantages: It can be known from the source code that the write operation copies “Arrays.Copyof ()”, and the memory of two objects will be stored in the memory at the same time, the old object and the newly written object, the memory occupied problem is obvious, if the object is large, it is easy to happen Yong GC and Full GC