请举例说明集合类是不安全的,面试加分项:你在开发中遇到过哪些问题、遇到过哪些异常?

请举例说明集合类是不安全的,面试加分项:你在开发中遇到过哪些问题、遇到过哪些异常?

异常对象: java.util.ConcurrentModificationException并发修改异常

异常情况:

每次出现错误的情况都不一样,在程序运行正常的情况下,有时空值,有时有值,有时还会报异常

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

导致原因:

ArrayList集合是线程不安全的,又要读数据,又要写数据

解决方案:

方法一:使用Vector代替ArrayList,因为Vector是线程安全的。
方法二:把一个线程不安全的转化成线程安全的,即List<String> list = Collections.synchronizedList(new ArrayList<>());
方式三:使用高并发解决 List<String> list = new CopyOnWriteArrayList<>();最重要

不准回答加锁,因为加锁属于“重复造轮子”,Java已经有了安全集合Vector

分析:
1、使用ArrayList,写入数据时线程不安全,但读取效率高
2、使用Vector,线程安全,但读取效率低
3、使用CopyOnWriteArrayList,读写分离,读取效率高,写入数据线程安全

代码:

package com.monster.ticket.communication;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Monster
 * @version v1.0
 * @time 03-29-2021 22:55:02
 * @description: 请举例说明集合类是不安全的,面试:你在开发中遇到过哪些问题
 */
public class NotSafeDemo {

    public static void main(String[] args) {
        // List<String> list = new ArrayList<>();
        // List<String> list = new Vector<>();
        // List<String> list = Collections.synchronizedList(new ArrayList<>());
        List<String> list = new CopyOnWriteArrayList<>();


        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                String str = UUID.randomUUID().toString().substring(0, 8);
                list.add(str);
                System.out.println(Thread.currentThread().getName() + "\t" + list);
            }, String.valueOf(i)).start();
        }
    }
}

CopyOnWriteArrayList原理分析

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

源码分析

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return {@code true} (as specified by {@link Collection#add})
 */
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();
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值