ConcurrentModificationException | 併發訪問異常

異常的產生:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//寫
list.add("a");
//讀
System.out.println(list);
},String.valueOf(i)).start();
}
}
}

同時對list集合進行讀寫操作導致的併發修改異常。


解決辦法:

1、Vector(線程安全的,不用多解釋)

在這裏插入圖片描述

2、Collections.synchronizedList
3、JUC:CopyOnWriteArrayList
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread((()->{
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("a");
System.out.println(list);
})).start();
}
}
}

CopyOnWrite 寫時複製,當我們往⼀個容器添加元素的時候,不是直接給容器添加,⽽是先將當前容器複製⼀份,向新的容器中添加數據,添加完成之後,再將原容器的引⽤指向新的容器。(操作的不是同一個集合對象其實,實現讀寫分離)

在這裏插入圖片描述Set版:

import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 0; i < 10; i++) {
final int temp = i;
new Thread((()->{
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
set.add(String.valueOf(temp)+"a");
System.out.println(set);
})).start();
}
}
}

Map版:

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Map<String,String> map = new ConcurrentHashMap<>();
for (int i = 0; i < 10; i++) {
final int temp = i;
new Thread((()->{
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//UUID.randomUUID().toString()是javaJDK(1.5以上的版本) 提供的一個自動生成主鍵的方法,它生成的是以爲32位的數字和字母組合的字符,中間還參雜着4個 - 符號。
map.put(UUID.randomUUID().toString().substring(0,3),UUID.randomUUID().toStrin
g().substring(0,2));
System.out.println(map);
})).start();
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章