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
的執行緒安全。
- 使用傳統的Vector集合類。但是該類在方法上加上Synchronize關鍵字,保證執行緒安全。但是jdl已經不
不推薦了,因為才用了重量級方式,導致執行效率低。 - 使用工具,
Collections.synchronizedList
保證執行緒安全。比如
List<String> 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的面試題目,一般該如何回答。
最後大黃分享多年面試心得。面試中,面對一個問題,大概按照總分的邏輯回答即可。先直接丟擲結論,然後舉例論證自己的結論。一定要第一時間抓住面試官的心裡,否則容易給人抓不著重點或者不著邊際的印象。
番外
另外,關注大黃奔跑公眾號,第一時間收穫獨家整理的面試實戰記錄及面試知識點總結。
我是大黃,一個只會寫HelloWorld
的程式設計師,咱們下期見。