JUC多线程及高并发10---集合类不安全

23 篇文章 0 订阅
13 篇文章 0 订阅

集合类不安全之并发修改异常

问题:我们知道ArrayList是线程不安全,请编码写一个不安全的案例并给出解决方案。

package ArrayList;

import java.util.ArrayList;

/*
* 集合类不安全的问题
* ArrayList
* */
public class ContainerNotSafeDemo {
    public static void main(String[] args) {
        //ArrayList是对数组的包装
        //第一问当我new一个 ArrayList,底层是什么?--------数组
        //第二问什么类型的数组?--------这里为整型 <泛型>(当你new的时候,Constructs an empty list with an initial capacity of ten.)
    new ArrayList<Integer>();
    }
}

 

接着看elementData是什么?

  public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

是一个 Object数组

transient Object[] elementData;

列表为什么为空?

因为DEFAULTCAPACITY_EMPTY_ELEMENTDATA为空

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

 当add添加1

public class ContainerNotSafeDemo {
    public static void main(String[] args) {
        //ArrayList是对数组的包装
        //第一问当我new一个 ArrayList,底层是什么?--------数组
        //第二问什么类型的数组?--------这里为整型(当你new的时候,Constructs an empty list with an initial capacity of ten.)
    new ArrayList<Integer>().add(1);
    }

这时size+1,而size初始值为0. 

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

如果超过10,需要扩容。

举例----单线程程比较安全

一般不会出错

package ArrayList;

import java.util.ArrayList;
import java.util.List;

/*
* 集合类不安全的问题
* ArrayList
* */
public class ContainerNotSafeDemo {
    public static void main(String[] args) {
        //ArrayList是对数组的包装
        //第一问当我new一个 ArrayList,底层是什么?--------数组
        //第二问什么类型的数组?--------这里为整型(当你new的时候,Constructs an empty list with an initial capacity of ten.)
//    new ArrayList<Integer>().add(1);

        List<String> list=new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        for (String element : list){
            System.out.println(element);
        }
    }
}

 结果

a
b
c

Process finished with exit code 0

多线程 

public class ContainerNotSafeDemo {
    public static void main(String[] args) {
        //ArrayList是对数组的包装
        //第一问当我new一个 ArrayList,底层是什么?--------数组
        //第二问什么类型的数组?--------这里为整型(当你new的时候,Constructs an empty list with an initial capacity of ten.)
//    new ArrayList<Integer>().add(1);

        List<String> list=new ArrayList<>();



        //多线程
        for (int i = 1; i <= 3; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

 结果不正确,但是没报错,证明了线程不安全

[null, 244aa3b3]
[null, 244aa3b3, 3a1a3d91]
[null, 244aa3b3]

Process finished with exit code 0

当  i<=30时

结果

"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:F:\idea2019\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=49644:F:\idea2019\IntelliJ IDEA 2019.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;F:\039_面试视频\笔记\out\production\笔记;F:\039_面试视频\笔记\lib\lombok-1.16.20.jar" ArrayList.ContainerNotSafeDemo
[e9b0e33b, ec95100c]
[e9b0e33b, ec95100c, 15ae19fc]
Exception in thread "14" [e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2]
Exception in thread "28" [e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177]
Exception in thread "23" [e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292]
Exception in thread "17" Exception in thread "15" [e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849]
Exception in thread "3" [e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919, a1f02e5a]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919, a1f02e5a, e445a60c]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919, a1f02e5a, e445a60c, eb5bfb7c]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919, a1f02e5a, e445a60c, eb5bfb7c, e5d9be52]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a, 599149d9, 3e15749c, e8351919, a1f02e5a, e445a60c, eb5bfb7c, e5d9be52, 9a1301d0]
[e9b0e33b, ec95100c, 15ae19fc, 9b4b0406, 67a91cb2, 97b61c27, 4d7ae7fc, 9e3c5177, bc7d6d89, 5ab2c07c, 593711f3, 1fad7d27, 1acc8cd2, decac026, 4b899326, 23c0c292, 22d8ff11, 9c663849, c77fdb58, 37efc073, 31ed5bbb, 3363a98a]
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	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 ArrayList.ContainerNotSafeDemo.lambda$main$0(ContainerNotSafeDemo.java:32)
	at java.lang.Thread.run(Thread.java:748)

Process finished with exit code 0

其中 java.util.ConcurrentModificationException 是ArrayList线程不安全在高并发多线程访问下面的异常。

Concurrent-----并发

Modification----修改

ConcurrentModificationException -----并发修改的异常

 

解决的例子

1.线程安全用 Vector<>

线程不安全,不考虑用性能的ArrayList

   List<String> list= new Vector<>();

2.其中了解collection、collections区别,前者为接口,后者为类

List<String> list=Collections.synchronizedList(new ArrayList<>());

 3.CopyOnWriteArrayList<>();

List<String> list= new CopyOnWriteArrayList<>();

 

1.故障现象
    Java.util.ConcurrentModificationException
2.导致原因
   并发争抢修改导致,参考花名册签名情况。
   一个人正在写入,另一个人过来抢夺,导致数据不一致异常。并发修改异常。

 3.解决方案
   3.1  new  Vector<>();----------(List<String> list=new Vector<>();)
   3.2   Collections.synchronizedList(new ArrayList<>());
   3.3   new CopyOnWriteArrayList<>();
4.优化建议(同样的错误不犯第二次)

 

笔记 

写实复制

CopyOnWrite容器即写实复制的容器。往一个容器添加元素的时候,不直接往当前容器object【】添加,而是先将当前容器object【】进行copy,复制出一个新的容器object【】 newElements,然后新的容器object【】newElements里添加元素,添加完元素之后,再将原容器的引用指向新的容器setArray(newElements);这样做的好处是可以对copyonWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以copyonWrite容器也是一种读写分离的思想,读和写不同的容器

  public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值