读写分离

读方法:读操作在原始数组中进行

  1. @SuppressWarnings("unchecked")
  2. private E get(Object[] a, int index) {
  3. return (E) a[index];
  4. }

写方法:
写操作在一个复制的数组上进行
写操作需要加锁,防止并发写入时导致写入数据丢失
写操作结束之后需要把原始数组指向新的复制数组

  1. public boolean add(E e) {
  2. final ReentrantLock lock = this.lock;
  3. lock.lock();
  4. try {
  5. Object[] elements = getArray();
  6. int len = elements.length;
  7. Object[] newElements = Arrays.copyOf(elements, len + 1);
  8. newElements[len] = e;
  9. setArray(newElements);
  10. return true;
  11. } finally {
  12. lock.unlock();
  13. }
  14. }
  15. final void setArray(Object[] a) {
  16. array = a;
  17. }

CopyOnWriteArrayList 在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景。
但是 CopyOnWriteArrayList 有其缺陷:

  • 内存占用:在写操作时需要复制一个新的数组,使得内存占用为原来的两倍左右;
  • 数据不一致:读操作不能读取实时性的数据,因为部分写操作的数据还未同步到读数组中。

所以 CopyOnWriteArrayList 不适合内存敏感以及对实时性要求很高的场景。