ArrayList
public static void main(String[] args) {
List list=new ArrayList();
list.add("11");
list.add("22");
list.add("33");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(list);
Object next = iterator.next();
System.out.println(next);
if(next.equals("11")){
list.remove("22");
}
if(next.equals("33")){
list.add("2222");
}
}
}
CopyOnWriteArrayList
public static void main(String[] args) {
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
list.add("11");
list.add("22");
list.add("33");
list.add("44");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(list);
Object next = iterator.next();
System.out.println(next);
if (next.equals("11")) {
list.remove("22");
}
if (next.equals("33")) {
list.add("2222");
}
}
}
通过案例我们可以发现 ArrayList 迭代修改的时候会 抛出异常 ,而CopyOnWriteArrayList 不会
CopyOnWrite的含义
创建新副本、读写分离
不可变原理
迭代的时候
我们看下ArrayList 源码为什么会报错
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
点开方法,他会进行一个比较操作所以会出现异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
我们看下 CopyOnWriteArrayList 源码
这是CopyOnWriteArrayList存放数据的地方,只能通过getArray获取
并且他会上锁,用的ReentrantLock
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
初始化 :构造函数 新建个空的数组
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
/**
* Creates an empty list.
*/
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
add 方法
/**
* 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();
//获取长度 //copy出一个新的数组
Object[] newElements = Arrays.copyOf(elements, len + 1);
//将我们的参数添加到这个位置
newElements[len] = e;
//set方法添加至
setArray(newElements);
return true;
} finally {
//释放锁
lock.unlock();
}
}
get方法
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
public boolean hasNext() {
return cursor < snapshot.length;
}
public boolean hasPrevious() {
return cursor > 0;
}
@SuppressWarnings("unchecked")
public E next() {
//判断 true 和 false
//逻辑简单了许多
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
本文地址:https://blog.csdn.net/qq_41977838/article/details/107051046
如对本文有疑问, 点击进行留言回复!!
解决idea中出现“illegal character U+200B” 问题
荐 为什么加了@Transactional注解,事务没有回滚?
Attribute ‘sklearn.linear_model._logistic.LogisticRegression.multi_class‘ must be explicitly set to
Java/Python实现 LeetCode剑指Offer 14-I.剪绳子(动态规划)
网友评论