集合类线程不安全问题

  1. new ArrayList(); 底层new的是什么?
    数组

  2. 凡是数组,一定有类型,请问new出来的数组是什么类型? // 超过10怎么扩容?
    Objiect类型

  3. 既然是数组,必然在内存中占据连续的内存空间,请问初始值为多少?(java8为例)
    10(懒加载的方式)

源码中的构造方法:
   /**
    * Constructs an empty list with an initial capacity of ten.
    */
   public ArrayList() {
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
   }
  1. 当数组元素超过初始内存大小的时候,会扩容机制,请详细介绍一下扩容机制?
    扩容的方式:原子的一半 (10–>15)
   /**
    * Increases the capacity to ensure that it can hold at least the
    * number of elements specified by the minimum capacity argument.
    *
    * @param minCapacity the desired minimum capacity
    */
   private void grow(int minCapacity) {
       // overflow-conscious code
       int oldCapacity = elementData.length;
       int newCapacity = oldCapacity + (oldCapacity >> 1);
       if (newCapacity - minCapacity < 0)
           newCapacity = minCapacity;
       if (newCapacity - MAX_ARRAY_SIZE > 0)
           newCapacity = hugeCapacity(minCapacity);
       // minCapacity is usually close to size, so this is a win:
       elementData = Arrays.copyOf(elementData, newCapacity);
   }
  1. 扩容源码:拷贝方法==>Arrays.CopyOf

  2. 第二次扩容是多少:15–>22(向下取整)

  3. 是否线程安全?
    不安全,因为add方法为了保证并发性的效率,没有加锁。

  /**
    * Appends the specified element to the end of this list.
    *
    * @param e element to be appended to this list
    * @return <tt>true</tt> (as specified by {@link Collection#add})
    */
   public boolean add(E e) {
       ensureCapacityInternal(size + 1);  // Increments modCount!!
       elementData[size++] = e;
       return true;
   }
  1. 请举例线程不安全的代码。
   public static void main(String[] args) {
       List<String> list = new ArrayList<String>();
       for (int i = 1; i < 50; i++) {
           new Thread(()->{
               list.add(UUID.randomUUID().toString().substring(0,6));
               System.out.println(list);
           }, String.valueOf(i)).start();
       }
   }

在这里插入图片描述
  (1)解决方案一:用Vector
在这里插入图片描述

vector中的add源码
   /**
    * Appends the specified element to the end of this Vector.
    *
    * @param e element to be appended to this Vector
    * @return {@code true} (as specified by {@link Collection#add})
    * @since 1.2
    */
   public synchronized boolean add(E e) {
       modCount++;
       ensureCapacityHelper(elementCount + 1);
       elementData[elementCount++] = e;
       return true;
   }

  (2)解决方案二:用Collections 工具类
    附带面试题:Collection & Collections 的区别?

List<String> list = Collections.synchronizedList(new ArrayList<String>()); // 方式二,相当于再次包上一层安全方式。

  (3)解决方案二:用CopyOnWriteArrayList

List<String> list = new CopyOnWriteArrayList<>(); // 方式三,读写分离的思想。

在这里插入图片描述

每次加1,写的时候加锁,读的时候不加锁。
   /**
    * 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();
       }
   }
  1. HashSet的底层数据结构是啥?
    HashMap
   /**
    * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
    * default initial capacity (16) and load factor (0.75).
    */
   public HashSet() {
       map = new HashMap<>();
   }
  1. HashSet中的add方法是仅仅需要一个值,HashMap中的add()方法是需要键值对,不匹配,如何解释?
    只关心key,value都是常量PRESENT。
  /**
    * Adds the specified element to this set if it is not already present.
    * More formally, adds the specified element <tt>e</tt> to this set if
    * this set contains no element <tt>e2</tt> such that
    * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
    * If this set already contains the element, the call leaves the set
    * unchanged and returns <tt>false</tt>.
    *
    * @param e element to be added to this set
    * @return <tt>true</tt> if this set did not already contain the specified
    * element
    */
   public boolean add(E e) {
       return map.put(e, PRESENT)==null;
   }

也是线程不安全的,解决方法用:ConcurrentHashMap

Map<String, String> map = new ConcurrentHashMap<>();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值