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();
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章