多线程下如何使用List集合

  1. 使用Collections.synchronizedArrayList(),在集合增删改操作上加synchronized锁。默认使用的是当前对象(即创建的synchronized集合),也可以传入要锁的对象。
  2. 使用CopyOnWriteArrayList类进行读写分离:

写时复制,当添加元素时,不直接在原数组上添加,而是先copy数组,复制出一个新容器,然后再新容器中加入元素,添加完元素再将引用指向新容器,这样可以并发的读,而不会读写互斥、提高效率。
但是写时还是要加锁,保证只有一个线程在进行写操作。
为了保证写线程替换数组后对其他读线程立即可见:array数组使用volatile进行修饰。

  1. /** The lock protecting all mutators */
  2. final transient ReentrantLock lock = new ReentrantLock();
  3. /** The array, accessed only via getArray/setArray. */
  4. private transient volatile Object[] array;
  1. public E set(int index, E element) {
  2. final ReentrantLock lock = this.lock;
  3. lock.lock(); // 加锁 保证写操作的并发安全
  4. try {
  5. Object[] elements = getArray();
  6. E oldValue = get(elements, index);
  7. if (oldValue != element) {
  8. int len = elements.length;
  9. Object[] newElements = Arrays.copyOf(elements, len);
  10. newElements[index] = element;
  11. setArray(newElements);
  12. } else {
  13. // Not quite a no-op; ensures volatile write semantics
  14. setArray(elements);
  15. }
  16. return oldValue;
  17. } finally {
  18. lock.unlock();
  19. }
  20. }