java中常见的集合类大部分是非线程安全的,在多线程情况下会报并发修改异常(ConcurrentModificationException)
并发下的ArrayList类:
1 //集合类不安全的例子 2 public class CollectionNotSafe { 3 4 public static void main(String[] args) { 5 6 List<String> list = new ArrayList<>(); 7 for (int i = 0; i < 50; i++) { 8 new Thread(()->{ 9 list.add(UUID.randomUUID().toString().substring(0,8)); 10 System.out.println(list); 11 },String.valueOf(i)).start(); 12 } 13 14 } 15 }
16 //运行结果: ConcurrentModificationException
解决办法:使用集合的工具类Collections包中的synchronizedList(),
或者直接使用java.util.concurrent包中的CopyOnWriteArrayList
List<String> saveList1 = Collections.synchronizedList(new ArrayList<>()); List<String> saveList2 = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList底层是一个volatile修饰的Object数组,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();
}
}
set和map的道理与list的相同,都可以在concurrent包中找到线程安全的集合类(CopyOnWriteArraySet,ConcurrentHashMap),或者使用Collctions包中的方法。