测试案例:
import lombok.extern.slf4j.Slf4j;
import net.jcip.annotations.ThreadSafe;
import java.util.List;
import java.util.concurrent.*;
@ThreadSafe
@Slf4j
public class CopyOnWriteListExample {
// 请求总数
public static int requestTotal = 2000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static List<Integer> list = new CopyOnWriteArrayList<>();
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(requestTotal);
for (int i=0;i<requestTotal;i++) {
final int num = i;
executorService.execute(() -> {
try {
semaphore.acquire();
add(num);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
log.info("{}", list.size());
}
private static void add(int i) {
list.add(i);
}
}
add方法源码:
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 数组copy
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 新增对象添加到新copy的数组
newElements[len] = e;
// 引用指向新数据
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
由此上可知,CopyOnWriteArrayList适合多读少写的场景