涉及到的常用类
- ArrayList
- HashSet
- HashMap
在多线程下比较容易出现的异常是 java.util.ConcurrentModificationException,也就是并发修改异常。这个是由于并发争抢修改导致写入数据中断,数据出现异常
案例演示
故障现象
java.util.ConcurrentModificationException
解决方案
方案一:使用线程安全的list类
方案二:使用集合工具类
方案三:使用写时复制 CopyOnWriteArrayList
优化建议
采用方案三。
理由:
Vector和工具类都是使用了同步锁,效率低下,而CopyOnWriteArrayList则不同,可以看一下源码
从源码可以看出,这里使用了可重入锁,其效率高于synchronized。其次,这里使用的是写时复制,是将当前的容器Object[ ] elements进行copy,其实底层就是数组的复制,复制出一个新的容器Object[ ] newElements,然后向新的容器中添加元素,添加完元素后,将原容器的引用指向新的容器,setArray(newElements)。这样做的好处是可以并发读而不需要加锁,因为当前的元素不需要添加元素,所有CopyOnWriteArrayList也是一种读写分离的思想,读和写是不同的容器。
剩下的HashSet和HashMap也是类似的解决方案。例如:
HashSet
CopyOnWriteArraySet 其实就是使用的CopyOnWriteArrayList
HashMap
这里的ConcurrentHashMap在1.7使用的分段锁,1.8又改成了红黑树,这里不再赘述,详见ConcurrentHashMap