1. 程式人生 > 其它 >Java面試必考題-ArrayList常見知識點

Java面試必考題-ArrayList常見知識點

技術標籤:Java面試題目

微信公眾號:大黃奔跑
關注我,可瞭解更多有趣的面試相關問題。

文章目錄

寫在之前

對於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的執行緒安全。

  1. 使用傳統的Vector集合類。但是該類在方法上加上Synchronize關鍵字,保證執行緒安全。但是jdl已經不
    不推薦了,因為才用了重量級方式,導致執行效率低。
  2. 使用工具,Collections.synchronizedList保證執行緒安全。比如
    List<String> lists = Collections.synchronizedList(new ArrayList <>());
  3. 利用寫時複製的集合類。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的面試題目,一般該如何回答。

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

番外

另外,關注大黃奔跑公眾號,第一時間收穫獨家整理的面試實戰記錄及面試知識點總結。

我是大黃,一個只會寫HelloWorld的程式設計師,咱們下期見。

關注大黃,充當offer收割機