ArrayList線程不安全
public static void main(String[] args) {
List<String> list= new ArrayList<>();
for (int i = 1; i <=30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(1,8));
System.out.println(list);
},String.valueOf(i)).start();
}
多線程操作時會發生java.util.ConcurrentModificationException
解決方案
- Vector
- Collections.synchronizedList(new ArrayList<>());
- CopyOnWriteArrayList
public static void main(String[] args) {
List<String> list= new CopyOnWriteArrayList<>();
for (int i = 1; i <=30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(1,8));
System.out.println(list);
},String.valueOf(i)).start();
}
寫時複製
寫時複製 copyOnWrite 容器即寫時複製的容器 往容器添加元素的時候,不直接往當前容器object[]添加,而是先將當前容器object[]進行copy,複製出一個新的object[] newElements 然後向新容器object[] newElements 裏面添加元素 添加元素後,再將原容器的引用指向新的容器 setArray(newElements);這樣的好處是可以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線程不安全,CopyOnWriteHashSet線程安全
HashMap線程不安全,ConcurrentHashMap線程安全