测试案例:
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适合多读少写的场景