java集合类问题是java基础中的重点,也是面试必问的一个东西,面试官很明确的告诉我们了:就要问你这个,就看你能学多少。
List list = new ArrayList();>();
当我们执行这条代码的时候,底层做了什么操作呢?我们来看下源码:

底层创建了一个空数组,默认的初始容量为10
执行add()方法往集合中添加元素的时候,如果集合中的元素超过了10个,那么就会进行扩容,会扩大为原来的1.5倍
在单线程环境下,ArrayList是安全的
public class CollectionNotSafeDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("c");for (String element:list){System.out.println(element);}}}

但在多线程的情况下,使用ArrayList就会有问题了
public class CollectionNotSafeDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();for (int i=1;i<=30;i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);}).start();}}}

多线程情况下会报 并发修改异常
为什么呢?

我们会发现,add()方法上面是没有加synchronized的,所以并发写的时候,就会出现问题:一个人正在写,另一个人过来争抢,导致数据不一致,这就是并发修改异常。
那么怎么解决并发修改异常呢?
有三种方法:
-
new Vector<>()
public class CollectionNotSafeDemo {public static void main(String[] args) {List<String> list = new Vector<>();for (int i=1;i<=30;i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);}).start();}}}
-
Collections.synchronizedList(new ArrayList<>())
public class CollectionNotSafeDemo {public static void main(String[] args) {List<String> list = Collections.synchronizedList(new ArrayList<>());for (int i=1;i<=30;i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);}).start();}}}
-
new CopyOnWriteArrayList<>()
public class CollectionNotSafeDemo {public static void main(String[] args) {List<String> list = new CopyOnWriteArrayList<>();for (int i=1;i<=30;i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);}).start();}}}
List是这种情况,那么同属Collection下的Set呢?
没错,在多线程情况下,set和list的问题是一样,在这里我就不展示代码了,感兴趣的话大家可以去试试。
最后我们再来看一下Map是什么情况呢?
在多线程情况下:map也会发生并发修改异常
public class CollectionNotSafeDemo {public static void main(String[] args) {Map<String,Object> map = new HashMap<>();for (int i = 1; i <= 30; i++) {new Thread(()->{map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));System.out.println(map);},String.valueOf(i)).start();}}}

解决办法有两种:
-
Collections.synchronizedMap(new HashMap<>())
public class CollectionNotSafeDemo {public static void main(String[] args) {Map<String,Object> map = Collections.synchronizedMap(new HashMap<>());for (int i = 1; i <= 30; i++) {new Thread(()->{map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));System.out.println(map);},String.valueOf(i)).start();}}}
-
ConcurrentHashMap
public class CollectionNotSafeDemo {public static void main(String[] args) {Map<String,Object> map = new ConcurrentHashMap<>();for (int i = 1; i <= 30; i++) {new Thread(()->{map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));System.out.println(map);},String.valueOf(i)).start();}}}
遇到线程安全问题的话,我们通常会去考虑使用JUC下的一些类。
最后
以上就是热情镜子最近收集整理的关于Collection线程不安全问题的全部内容,更多相关Collection线程不安全问题内容请搜索靠谱客的其他文章。
发表评论 取消回复