JAVA高并发(JUC)之集合不安全

   日期:2020-05-07     浏览:93    评论:0    
核心提示:首先是我们的ArrayList:这次我们讲解的是集合的不安全,首先我们都知道ArrayList吧!首java

首先是我们的ArrayList:

这次我们讲解的是集合的不安全,首先我们都知道ArrayList吧!
首先我们拓展几个知识点,ArrayList底层是Object类型的数组,初始容量是10(jdk7之前,jdk8之后是空引用,到add之后会变成10,类似于懒加载的机制),其扩容的方式是每次扩容为之前的一半,比如10会扩容成15,15扩容成22,扩容用到的方法时Arrays的copyof方法,OK,接下来后进入主题。
先看这段代码:

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

之后我们通过Lambda表达式来生成几个线程

        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();
        }

之后会报异常:
java.util.ConcurrentModificationException 并发修改异常
导致原因:多线程并发争抢统一资源,且没加锁
那么我们有什么
解决办法呢??

方法一:

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

Vector集合,底层给add方法加了synchronized(重锁),同一时间段只有一个个线程,效率低,所以这就是为什么集合安全效率低的原因。

方法二:

Collections.synchronizedList(new ArrayList<>());

这是Connections的静态方法,传入一个ArrayList。

方法三:

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

这个JUC包的类,实现了List接口。
底层:volatile Object[] array
其add方法里面加了锁ReentrantLock

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();
        }
    }

**

接着我们来看Set集合:

同样扩展点知识点,HashSet底层数据结构是HashMap(源码构造器里面 new HashMap()),其add方法实际上return map.put(e,PRESENT)==null; PRESENT实际上就是一个object常亮,所以实际上就是HashMap的keys。
同样的步骤:

        Set<String> set=new HashSet<>();
        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();
        }

同样是报错:
java.util.ConcurrentModificationException
解决方案:
方法一:

Set<String> set=Collections.synchronizedSet(new HashSet<>());

方法二:

 Set<String> set=new CopyOnWriteArraySet();

也是JUC的里的类,其构造器其实new CopyOnWriteArrayList();

然后就是我们的Map:

扩展知识:HashMap初始容量,每次扩容为原值得一倍。

 Map<String, String> map = new HashMap<>();
        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();
        }

同样的会报错:
java.util.ConcurrentModificationException
解决办法:

 Map<String, String> map = new ConcurrentHashMap();

JUC包下。

这次就是本次讲解的JUC之集合不安全,希望能帮助到大家,如果有更好的建议,欢迎大家留言!

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服