1.ArrayList多线程下安全问题
1).故障现象 java.util.ConcurrentModificationException 并发修改异常
2).导致原因 List add()方法没有并发锁
并发争抢修改导致。
比如生活中花名册签名,一个人正在写,另一个同学过来抢夺,导致数据一致异常。并发修改异常
3).解决方案
(1) List lists=new Vector<>();
(2) List list= Collections.synchronizedList(new ArrayList<>());
(3) List list= new CopyOnWriteArrayList<>();
package register;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ContainerSafeDemo {
public static void main(String[] args) {
//List<String> list=new ArrayList<>();
// List<String> list=new Vector<>();
//List<String> list= Collections.synchronizedList(new ArrayList<>());
List<String> list= new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},"t1").start();
}
/**
* 1.故障现象 java.util.ConcurrentModificationException 并发修改异常
*
* 2.导致原因 List add()方法没有并发锁
* 并发争抢修改导致。
* 比如生活中花名册签名,一个人正在写,另一个同学过来抢夺,导致数据一致异常。并发修改异常
*
* 3.解决方案
* (1) List<String> lists=new Vector<>();
* (2) List<String> list= Collections.synchronizedList(new ArrayList<>());
* (3) List<String> list= new CopyOnWriteArrayList<>();
*/
}
/**
* CopyOnWriteArrayList类中add方法
* 写时复刻
* CopyOnWrite容器即写时复刻容器,往一个容器增加元素时候,不直接往当前Object[]中添加,而是将当前的容器Object[]进行Copy,
* 复刻一个新的容器Object[] newElements,然后新的容器object[] newElements里添加元素,添加元素之后,再将原容器的引用指向
* 新容器SetArray(newElement)。这样做的好处是可以对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();
* }
* }
*/
}
//线程不安全运行输出
[767bcef3, a308b93e, 30ff0511, 95520b2d, 9659785f]
Exception in thread "t1" Exception in thread "t1" Exception in thread "t1" Exception in thread "t1" java.util.ConcurrentModificationException
[767bcef3, a308b93e, 30ff0511, 95520b2d, 9659785f, 4adbf6ed, a06076e9, f1b7613e, 070642bd, c8e97a45]
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
//线程安全输出
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa, aad8fd64, 6013b202, c19ceb0f, 13ff89d4]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa, aad8fd64, 6013b202, c19ceb0f]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa, aad8fd64, 6013b202]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa, aad8fd64]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92, 72ebf1fa]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b]
[23fdafdd, d8ce0b4c, 1f8e8152, 2cdffe9b, fd408e92]
2 HashSet与HashMap都是线程不安全的,解决方法与List一样
Set<String> set=new CopyOnWriteArraySet<>();
Map<String,String> map=new ConcurrentHashMap<>();
3.HashSet底层是HashMap
HashSet add(key)----->HashMap put(key,Object PRESENT)


被折叠的 条评论
为什么被折叠?



