java面试-集合类不安全问题及解决方案

Posted wjh123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java面试-集合类不安全问题及解决方案相关的知识,希望对你有一定的参考价值。

一、List

1、代码演示

public class ArrayListNotSafeDemo 

    public static void main(String[] args) 
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= 30; i++) 
            new Thread(() -> 
                //Constructs an empty list with an initial capacity of ten.
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            , String.valueOf(i)).start();
        
    

2、故障现象

java.util.ConcurrentModificationException

3、导致原因

一个线程正在写,另一线程过来抢夺,导致数据不一致,即并发修改导致的异常

4、解决方案

  • new Vector<>()
  • Collections.synchronizedList()
  • new CopyOnWriteArrayList<>()   

         在读多写少的时候推荐使用 CopeOnWriteArrayList 这个类

         写时复制,读写分离的思想 好处:读操作完全无锁

         使用场景 :写操作非常少的场合,能容忍读写的短暂不一致。

                        CopyOnWriteArrayList迭代器是只读的,不支持增删改。

5、 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();
        
    

二、Set

1、代码演示:

public class HashSetNotSafeDemo 

    public static void main(String[] args) 
        Set<String> list = new HashSet<>();
        for (int i = 1; i <= 30; i++) 
            new Thread(() -> 
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            , String.valueOf(i)).start();
        
    

2、解决方案:

  • Collections.synchronizedSet()
  • new CopyOnWriteArraySet<>()   

3、CopyOnWriteArraySet底层源码:

底层使用CopyOnWriteArrayList

    public CopyOnWriteArraySet() 
        al = new CopyOnWriteArrayList<E>();
      

4、HashSet底层源码

HashSet的key是你add()的值,value是一个叫PRESENT Object类型的常量,即HashSet只关心key

    public HashSet() 
        map = new HashMap<>();
    

   
    private static final Object PRESENT = new Object();

    public boolean add(E e) 
        return map.put(e, PRESENT)==null;
      

三、Map  

1、代码演示:

public class HashMapNotSafeDemo 

    public static void main(String[] args) 
        Map<String, String> map = new HashMap<>();
        for (int i = 1; i <= 30; i++) 
            new Thread(() -> 
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
                System.out.println(map);
            , String.valueOf(i)).start();
        
    

2、解决方案

  • Collections.synchronizedMap()
  • new ConcurrentHashMap<>();

 

以上是关于java面试-集合类不安全问题及解决方案的主要内容,如果未能解决你的问题,请参考以下文章

Java并发多线程编程——集合类线程不安全之HashMap的示例及解决方案

面试官系统精讲Java源码及大厂真题系列之Java线程安全的解决办法

Java并发多线程编程——集合类线程不安全之HashSet的示例及解决方案

Java并发多线程编程——集合类线程不安全之ArrayList的示例及解决方案

集合类不安全_List_Set_HashMap

Java经典面试:源码解读及如何保证线程安全