java中常见的集合类大部分是非线程安全的,在多线程情况下会报并发修改异常(ConcurrentModificationException)
并发下的ArrayList类:
1 //集合类不安全的例子 2 public class CollectionNotSafe { 3 4 public static void main(String[] args) { 5 6 Listlist = 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
ListsaveList1 = Collections.synchronizedList(new ArrayList<>());List 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包中的方法。