您的位置:首页 > 运维架构

CopyOnWriteArrayList详解

2015-07-20 16:28 399 查看


<span style="font-family: 'Microsoft YaHei', Verdana, sans-serif, 宋体;">package com.zyh.concurrent.base;</span>
/**
* @类注释:
* @author: zhangyinhu
* @date 2015-7-20 下午4:31:49
*/

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CopyOnWriteArrayListTest {
private static class Read implements Runnable {
List<String> list;

public Read(List<String> list) {
this.list = list;
}

public void run() {
for (String s : list) {
System.out.println(s);
}
}
}
private static class Write implements Runnable {
List<String> list;
int index;

public Write(List<String> list, int index) {
this.list = list;
this.index = index;
}

public void run() {
list.remove(index);
list.add(index, "写方法_" + index);
}
}

public static void main(String[] args) {

new Runnable() {
@Override
public void run() {

final int NUM = 10;
List<String> list = new ArrayList<String>();//CopyOnWirteArrayList换成这个不会报错
for (int i = 0; i < NUM; i++) {
list.add("main方法" + i);
}
ExecutorService executorService = Executors.newFixedThreadPool(NUM);
for (int i = 0; i < NUM; i++) {
executorService.execute(new Read(list));
executorService.execute(new Write(list, i));
}
executorService.shutdown();
}
}.run();

}
}


会抛出异常

Exception in thread "pool-1-thread-2" java.util.ConcurrentModificationException

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)

at java.util.ArrayList$Itr.next(ArrayList.java:831)

at com.zyh.concurrent.base.CopyOnWriteArrayListDemo$Read.run(CopyOnWriteArrayListDemo.java:23)

CopyOnWriteArrayList

分析原因:
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (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();
}
}


CopyOnWriteArrayList源码得知是一个线程安全的类,在add的时候回把原来的数据copyof一份出来,然后在尾部进行"add"。

CopyOnWriteArrayList场景读操作大于写操作,比如缓存。会对老数据(copy)分离保证读的效率
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: