Java面試必考題——ArrayList常見知識點 寫在之前 面試回顧 源碼 總結

寫在之前

對於ArrayList的面試題目網上比較多,但是大多數從ArrayList的數據結構出發,比如查找、修改的等效率問題分析,本篇文章想從併發的角度入手,給大家講講ArrayList的併發問題該如何回答。

面試回顧

通常容器之類的問題由於比較基礎,一般在一面考察的比較多,同時這也成爲決定能否進入二面的關鍵因素。

面試官:我看你簡歷上面寫能夠熟練掌握Java基礎知識,平時有使用過哪些容器呢?

我:面試官您好,一般工作中使用的比較多的有ArrayList、LinkedList、HashSet、hashMap等。

面試官:那他們都是線程安全的嗎?

我:不是線程安全的,他們在高併發情況下都會有線程安全問題。

面試官:那你能寫一個程序簡單說說ArrayList會有哪些那問題嗎?

當然這時候肯定得拿出平時好好積累的程序了。

我:

如下:開啓20個線程,每個線程給生成一個隨機數,並且將隨機數添加到 list 容器中

public class ArrayListUnsafe {
    public static void main(String[] args) {
        List<String> lists = new ArrayList <>();
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(lists);
            },String.valueOf(i)).start();
        }
    }
}

通常情況下,這個程序會報 java.util.ConcurrentModificationException ,這也是高併發情況下常見的錯誤,併發修改異常

面試官:爲什麼會產生這種問題呢?

我:在多線程下,每次往容器中寫數據時,不保證順序,誰搶佔到了容器誰開始寫入數據,因此可能存在覆蓋情況,導致每次執行的結果都不一致。

面試官:有什麼辦法可以避免這種問題嗎?

我:現在jdk提供了多種方式保證 List 的線程安全。

使用傳統的Vector集合類。但是該類在方法上加上Synchronize關鍵字,保證線程安全。但是jdK已經不推薦了,因爲用了重量級加鎖方式,導致執行效率低。
使用工具, Collections.synchronizedList 保證線程安全。比如
List lists = Collections.synchronizedList(new ArrayList <>());
利用寫時複製的集合類。 CopyOnWriteArrayList
能夠說出寫時複製,這是加分項啊,同學們!!

面試官:能夠簡單說說什麼是 CopyOnWriteArrayList 嗎?

我:寫時複製類似於將讀數據和寫數據過程分離開來。比如

A線程和B線程都開始寫數據,A、B每次寫數據之前,都需要拿到一個許可證(類似於鎖),主內存中數據複製到工作內存中,然後再進行修改,修改完畢之後將容器的引用指向新的數據集,然後再允許別的線程修改。

源碼

比如對於寫時複製的 add() 方法, jdk 源碼如下:

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();
    }
}

每次添加元素的時候,先獲取鎖(也就是許可),之後纔去更新元素。

回答到這種程度, ArrayList 的問題已經算是回答的比較好了,如果一面每個問題都能夠回答上是什麼,爲什麼、怎麼做,進入二面必然是水到渠成的事兒了。

面試官:好了,今天的面試就到這裏,請問你下一場面試什麼時候有時間呢,我來安排一下。

哈哈哈,恭喜你,到了這裏面試已經成功拿下了,開心的準備二面吧

我:我這幾天都有時間的,看你們的安排。

總結

關於容器的問題諸多博客都有描述,關於ArrayList的底層數據結構,如果有同學感興趣可以自己搜索,這裏我就不拾人牙慧了。本文主要從線程安全的角度分析ArrayList的面試題目,一般該如何回答。

最後分享多年面試心得。面試中,面對一個問題,大概按照總分的邏輯回答即可。先直接拋出結論,然後舉例論證自己的結論。一定要第一時間抓住面試官的心裏,否則容易給人抓不着重點或者不着邊際的印象。

來源:https://www.tuicool.com/articles/rA77Bbu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章