JUC之集合

常见的有哪些是线程不安全的?

1、集合类是不安全的:ArrayList,HashSet,HashMap等等都是不安全

2、i++, ++i 也是不安全

JUC什么?

1、juc是java.util.concurrent包的简称,在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括线程池、异步IO 和轻量级任务框架。提供可调的、灵活的线程池。还提供了设计用于多线程上下文中的Collection 实现等

2、高并发最容易出现的异常是:

ConcurrentModificationException

3、高并发的项目不能使用ArraryList,只能使用juc报下的集合

 * 1    lambda Express
 *  1.1 如何写:    拷贝形括号,写死右箭头,落地大括号
 *  1.2 Lamdba 有且仅有一个方法,注解@FunctionalInterface
 *  1.3 default
 *  1.4 静态方法

一、题目:请举例说明集合类是不安全的—–面试题

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

        for (int i = 1; i <=30; i++)
        {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(1,4));
                System.out.println(list);
            },String.valueOf(i)).start();
        }

运行该代码会报:ConcurrentModificationException异常

为什么会出现这种情况?1.5版本之前是使用的线程安全,但是为了效率改成了不安全的,详情见https://blog.csdn.net/u012859681/article/details/78206494

二、使用JUC解决

原理:写时复制,这个类似于mysql的读写分离

 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[] ele ments = getArray();
     int len = elements.length;
     Object[] newElements = Arrays.copyOf(elements, len + 1);
     newElements[len] = e;
     setArray(newElements);
     return true;
     } finally {
     lock.unlock();
        }
     }

实现代码:

list—-CopyOnWriteArrayList

set—-CopyOnWriteArraySet

map—ConcurrentHashMap

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

        for (int i = 1; i <=30; i++)
        {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(1,4));
                System.out.println(list);
            },String.valueOf(i)).start();
        }

 Set<String> set = new CopyOnWriteArraySet<String>();

        for (int i = 1; i <=30; i++)
        {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(1,4));
                System.out.println(set);
            },String.valueOf(i)).start();
        }

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

        for (int i = 1; i <=30; i++)
        {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(1,4));
                System.out.println(map);
            },String.valueOf(i)).start();

        }

 

 

    原文作者:JUC
    原文地址: https://blog.csdn.net/student__software/article/details/81913125
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞