JAVA集合类的不安全

JAVA集合类的不安全

一、并发修改异常——ConcurrentModificationException
我们都知道ArrayList是线程不安全的,那么先举一个线程不安全的case,来看看到底怎么个不安全。


 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, 6));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }

以上代码运行结果

java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at java.util.AbstractCollection.toString(AbstractCollection.java:461)
	at java.lang.String.valueOf(String.java:2994)
	at java.io.PrintStream.println(PrintStream.java:821)
	at com.zhangfz.day02.NoSafeDemo.lambda$list$2(NoSafeDemo.java:64)

那到底问题出在哪呢?
在多线程的情况下,一个线程正在执行写操作当执行到一半时,突然另一个X线程抢到了执行权,也要执行写操作,而这时候就会导致并发修改异常。
解决办法:

  1. Vector集合可以解决。因为它的add方法加锁了,但是并不推荐使用,因为一旦加锁时间可以保证数据的一致性但却牺牲了并发性,也就是说没有效率
  2. Collections.synchronizedList(new ArrayList<>());实用工具类中的方法创建一个线程安全的集合,此种方法也不推荐
  3. CopyOnWriteArrayList();写时复制技术推荐使用

二、写时复制技术
什么是写时复制呢,那正如起名就是在写的时候复制一份出来去执行写操作。下面看源码
在这里插入图片描述
首先获取数组中的数据,然后获取数组长度。之后使用Arrays.copyOf()重新复制一个长度+1的数组,把要写入的数据加到最后,并set到数组中返回true.
使用写时复制可以让读的时候去读原来那一份数据,写的时候保证原子性。这也是一种读写分离的一种思想,也就是并发读,原子写。
三、Set
同样HashSet也是线程不安全的,其解决方案有两种:

  1. Collections.synchronizedSet();使用工具类(不推荐)
  2. new CopyOnWriteArraySet<>();JUC写时复制技术,原理同CopyOnWriteArrayList.

四、Map
Set不安全 ,而HashSet的底层是HashMap。那HashMap 自然也是不安全的
但Map的解决方案稍微不同,JUC 中并没有CopyOnWrite…的集合类,但是它有一个只有ConcurrentHashMap的集合类,其就是用来解决HashMap的不安全的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值