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
面试题为了方便查看直接搬运过来了: