一.出现的现象(并发修改异常(java.util.ConcurrentModificationException) )
二. 导致的原因
三.解决问题(写时复制(CopyOnWriteArrayList))
四.集合类不安全---Set
五.集合类不安全---Map
一.出现的故障现象
代码示例:
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ContainerNoSafeDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 1; i <=30 ; i++) {//30个线程之后出现异常
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
java.util.ConcurrentModificationException
二.导致的原因
并发争抢修改导致,一个写入,另一个抢夺,导致数据不一致异常。ArrayList下的add()方法为了保证并发性和效率没有加锁,所以导致线程不安全
三.解决问题
①使用vector
继承图如下,List接口下面有一个Vector实现类,Vector的addElement方法有sychonized
②Collections.synchronizedList(new ArrayList<>());
Collections是集合类,下面有synchronizedList方法可以保证线程安全
③new CopyOnWriteArrayList<>();
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();
}
}
四.集合类不安全---Set
1.HashSet和ArrayList相似也是线程不安全的,解决办法有:
①Collections.synchronizedSet(new HashSet<>())
②new CopyOnWriteArraySet<>() 注意:CopyOnWriteArraySet底层还是CopyOnWriteArrayList可看源码
2.HashSet底层是什么?
HashSet的底层是HashMap,但是new HashSet("a")中只传一个值,而HashMap是key和value存在,为什么会这样呢?因为HashSet的add方法key就是e,需要传的值,value是final Object修饰的PRESENT常量,所以只需要传一个key就行。
五.集合类不安全---Map
HashMap与ArrayList相似也是线程不安全的,解决办法有:
①new ConcurrentHashMap() 和CopyOnWriteArraySet类似都是juc下的包