Collections.synchronizedList的修改操作都加了锁,但是迭代器方法没有加锁,所以在输出时需要对list加锁,适用于写多读少;而CopyOnWriteArrayList的修改过程不加锁,会生成一个list的副本,修改的是list的副本,在修改过程中,其他线程可以继续读取原来list,直到新的list被修改,所以速度非常快,但是因为要生成副本,比较耗资源,所以适合写少读多的场景,Vector太重,已经不使用
package com.example.test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class TestArrayListSafe { public static void main(String args[]){ // List<Integer> list=new ArrayList<Integer>(); // 使用Collections.synchronizedList返回安全列表,配合手动synchronized读取列表保证线程安全 // List<Integer> list= Collections.synchronizedList(new ArrayList<Integer>()); // 使用copy-on-write模式保证线程安全,读多写少,遍历和修改都不需要加锁 List<Integer> list= new CopyOnWriteArrayList<Integer>(); new WriteThread(list).start(); new ReadThread(list).start(); } } class WriteThread extends Thread{ private final List<Integer> list; public WriteThread(List<Integer> list){ super("WriteThread"); this.list=list; } @Override public void run(){ // synchronizedList和CopyOnWriteArrayList返回的列表进行写操作时不需要加锁 for(int i=0;true;i++){ list.add(i); list.remove(0); } } } class ReadThread extends Thread{ private final List<Integer> list; public ReadThread(List<Integer> list){ super("ReadThread"); this.list=list; } public void run(){ while (true){ synchronized (list){// 如果是synchronizedList需要加锁 for(int n:list){ System.out.println(n); } } } } }使用ArrayList或者遍历Collections.synchronizedList()不加锁的结果 Exception in thread “ReadThread” java.util.ConcurrentModificationException at java.util.ArrayList I t r . c h e c k F o r C o m o d i f i c a t i o n ( A r r a y L i s t . j a v a : 909 ) a t j a v a . u t i l . A r r a y L i s t Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859) at com.example.test.ReadThread.run(TestArrayListSafe.java:52) 使用 Collections.synchronizedList()加锁或者CopyOnWriteArraryList()的结果: 4305372 4305372 4305372 4305372 4305372 4305372 4305372 4305372
其他常见并发包