概述
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线程不安全问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复