ArrayList 线程不安全
在多线程得环境下,线程会争抢资源,导致java.util.ConcurrentModificationException 并发修改异常
解决方法:
Vector
将ArrayList 替换成为Vector
原理:
*将指定的元素插入到此Vector的指定位置。
将当前在该位置的元素(如果有的话)和任何后继元素右移(将其索引加一)
源码:
/**
* Inserts the specified element at the specified position in this Vector.
* Shifts the element currently at that position (if any) and any
* subsequent elements to the right (adds one to their indices).
*将指定的元素插入到此Vector的指定位置。
*将当前在该位置的元素(如果有的话)和任何*后继元素右移(将其索引加一)
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index > size()})
* @since 1.2
*/
public void add(int index, E element) {
insertElementAt(element, index);
}
方法实现
public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1);
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
Collections.synchronizedList(new ArrayList<>());
原理:将不安全得ArrayList加锁变成线程安全的
一般不用
重点 :CopyOnWriteArrayList
原理
new CopyOnWriteArrayList<>(); 扩容+1,copyof //复制一份,实现读写分离,写的时候加锁
* 源码:CopyOnWriteArrayList 即写时复制容器,往一个容器添加元素的时候,不直接往当前容器 object[]
* 添加,复制出一个新的Object[] newElements, 然后新的容器Object[] newElement 里添加元素,添加元素之后
* 再将原容器的引用指向新的容器 setArray(newElements);这样做的好处是可以对CopyOnwrite容器进行并发的读取
* 而不需要加锁,因为当前容器不会添加任何元素,所以CopyOnwrite容器也是一种读写分离得思想,读和写得容器不同
*
源码
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
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();
}
}