集合类的线程不安全
ArrayList
List<String> list = new ArrayList<>();
ArrayList在多线程下不安全:
java.util.ConcurrentModificationException
- 原因:
并发争抢修改导致 - 解决方案:
- new Vector(),Vector集合类加了synchronized锁
- Collections.synchronizedList(new ArrayList<>())
- new CopyOnWriteArrayList()
写时复制
CopyOnWrite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器中添加,而是先将当前容器进行copy,复出一个新的容器,然后新的容器里加元素,添加完元素后,再将原容器的引用指向新的容器。这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何新的元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器
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();
}
}
HashSet
Set也是线程不安全的,同样也有上面的方法可以解决
注意:CopyOnWriteArraySet 的底层是用 CopyOnWriteArrayList 实现的
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
题外:HaseSet的底层是用HashMap实现的,之所以set只添加一个,而map添加两个的键值对,那是因为set的add()方法只在map中添加建,而值是添加的一个Object的常量。看源码:
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap
Map也是线程不安全的
这时候用到的实现类是ConcurrentHashMap(),同样Collections工具包也可以。