「Java」CopyOnWriteArrayList与Vector
我们都知道ArrayList是线程非安全的。如果我们想要得到一个线程安全的集合。有如下方式 new Vector<String>(); Collections.synchronizedList(new ArrayList<>()); new CopyOnWriteArrayList();
他们实现线程安全的方式
Vector :简单粗暴 // add public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } // get public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); } Collections.synchronizedList 与Vector类似,也是上种方式。
我们来看看CopyOnWriteArrayList是如何实现线程安全的
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(); } }
首先CopyOnWriteArrayList其采用的COW思想,即在读的时候使用原来了的集合对象,当需要对集合进行写操作时,我们就创建一个新的对象,提供的这个需要进行修改操作的线程,当所有迭代完成后,再将旧集合的指针指向修改后的新集合。没有扩容机制,减少了扩容浪费的时间。 还有与上边两种不同的是,CopyOnWriteArrayList的get()方法没有锁。