我们都知道ArrayList是线程非安全的。如果我们想要得到一个线程安全的集合。有如下方式
- new Vector
(); - 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()方法没有锁。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)