1.故障现象 :ArrayList的add()方法并没有使用synchronized所以是线程不安全的,会造成java.util.ConcurrentmodificationException(并发修改异常)
2.导致原因:并发争抢修改导致
3.解决办法(以ArrayList为例,其他类似)
3.1使用Vector代替ArrayList,相比Vector的add()方法加了synchronized锁,保证了一致性,但是并发性下降了。
3.2 使用Collections工具类,List list = Collections.synchronizedList(new ArrayList<>()); 集合的接口是Collection,集合工具类是Collections
3.3使用juc(java.util.concurrent)包下的CopyOnWriteArrayList();写时复制(读写分离的思想),add()底层对数组增加一个容量Array.copyOf(element,length+1),添加add进的数据,把原来的数组失效,setArray()添加后的新数组。
代码实现
public class ArrayListDemo {
public static void main(String[] args) {
// List<String> list = Arrays.asList("a","b","c");
//
// list.forEach(System.out::println);
//Map<String,String> map = new HashMap<>();
Map<String,String> map = new ConcurrentHashMap<>();
//Map<String,String> map = Collections.synchronizedMap(new HashMap<>());
//HashMap<String,String> map = new CopyOnWriteHashMap<>();
for (int i=0; i < 30; i++){
new Thread(()->{
map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
System.out.println(map);
},String.valueOf(i)).start();
}
Set<String> set = new HashSet<>();
//HashSet底层是HashMap,
// 但是为啥HashSet的add只要一个值,
// 因为HashSet只有key变,value是一个PRESENT常量
set.add("a");
// Set<String> set1 = new ConcurrentHashSet<>();
//Set<String> set = Collections.synchronizedSet(new HashSet<>());
//Set<String> set = new CopyOnWriteArraySet();
for (int i=0; i < 30; i++){
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(set);
},String.valueOf(i)).start();
}
//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 < 30; i++){
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},String.valueOf(i)).start();
}
/**
* 1.故障现象:java.util.ConcurrentModificationException
*
* 2.导致原因
*
* 3.解决方案(ArrayList、HashSet、HashMap一样)
* (1)使用vector()
* (2)使用collections工具类下的synchronizedList()
* List<String> list = new synchronizedList(new ArrarList());
* 把线程不安全的ArrayList封装一层变成线程安全的。
* (3)JUC(java.util.concurrent)包下的CopyOnWriteArrayList()
*
* 4.优化建议(同样错误不犯第二次)
*
*/
}
}
HashMap、HashTable、ConcurrentHashMap区别
https://www.jianshu.com/p/5dbaa6707017这个链接底层讲的很详细。
HashMap和HashTable底层原理,即相关面试题,可以参考下面博客,很详细
https://blog.csdn.net/suifeng629/article/details/82179996
面试题为了方便查看直接搬运过来了: