• 基础巩固篇 —— 对不安全集合的理解


    一、不安全集合类

    说到不安全的集合类,一般会想到ArrayList,HashSet,HashMap,这三种最常用的。

    二、ArrayList类的不安全性

    不安全原因

    ArrayList的底层是数组,new ArrayList()是定义一个空数组{},当添加数据的时候进行扩容,初次扩容容量默认为10,通过Arrays.copyOf(elementData, newCapacity)进行数组复制,实现扩容。为了满足高并发需求,并没有对ArrayList内的方法进行同步实现,这样就会出现多个线程同时进行数组复制操作,然后数据复制异常(ConcurrentModificationException)

    解决方案

    1. 使用ArrayList的安全类Vector,Vector中的方法都是被synchronized关键字修饰的,每次调用添加方法只允许一个线程进行操作,保证了线程安全,降低并发量
    2. 使用Collectoins工具类的同步包装方法
    List<String> list = Collections.synchronizedList(new ArrayList<>());
    
    1. 使用java.util.concurrent包下的CopyOnWriteArrayList类
    • 代码:
    List<String> list = new CopyOnWriteArrayList<>();
    // 添加方法的源码
    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();
            }
        }
    
    • 原理:在进行add方法时添加了ReentrantLock非公平锁,这样就可以保证只能由一个线程进行写操作

    二、HashSet类的不安全性

    不安全原因

    HashSet的底层是HashMap,new HashSet()是new HashMap(),当添加数据的时候,添加的数据作为map的key,value为固定值PRESENT = new Object()。高并发情况下,进行抢占式写入操作时也会造成并发更新数据异常(ConcurrentModificationException)

    解决方案

    1. 使用Collectoins工具类的同步包装方法
    Set<String> set = Collections.synchronizedSet(new HashSet<>());
    
    1. 使用java.util.concurrent包下的CopyOnWriteArraySet类
    • 代码:
    Set<String> set = new CopyOnWriteArraySet<>();
    // 底层调用还是CopyOnWriteArraySet
    public CopyOnWriteArraySet() {
            al = new CopyOnWriteArrayList<E>();
        }
    

    三、HashMap类的不安全性

    不安全原因

    HashMap的底层是数组+链表结构。高并发情况下,进行抢占式写入操作时也会造成并发更新数据异常(ConcurrentModificationException)

    解决方案

    1. 使用Collectoins工具类的同步包装方法
    Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());
    
    1. 使用java.util.concurrent包下的ConcurrentHashMap类,它实现了ConcurrentMap接口
    • 代码:
    Map<String, Object> map = new ConcurrentHashMap<>();
    
  • 相关阅读:
    收藏好博客
    iOS设备的重力感应
    局域网内通过UDP协议进行传输接受数据——AsyncUdpSocket
    定时器NSTimer的用法
    线程数:5,ramp-up:1,循环::10 和 线程数:10,ramp-up:10,循环数:1,这两种情况有没有区别?
    什么是性能测试?
    JMeter 之 XPath提取器
    DNS--安装&&配置文件
    DNS--简介&&解析过程
    Tomcat--隐藏版本号
  • 原文地址:https://www.cnblogs.com/zzb-yp/p/15034893.html
Copyright © 2020-2023  润新知