2021屆Java開發求職-------面試實戰之百度實習

介紹

轉自牛客網:

1. 有看過HashMap源碼嗎?

hashmap還是比較常見,目前看到的每個面經都考這個

2. JDK1.7中HashMap的put()方法全過程。

注意hash值相等的話形成鏈表是用頭插法插入的

3. JDK1.8有那些變化。

jdk1.8新增紅黑樹改善hash碰撞帶來的鏈表過長而導致的查詢效率問題,並且擴容時是用尾插法

4. JDK1.7當中HashMap中線程不安全問題有那些?原因分別是什麼?

(1)在put的時候,因爲該方法不是同步的,假如有兩個線程A,B它們的put的key的hash值相同,不論是從頭插入還是從尾插入,假如A獲取了插入位置爲x,但是還未插入,此時B也計算出待插入位置爲x,則不論AB插入的先後順序肯定有一個會丟失

(2)在擴容的時候,jdk1.8之前是採用頭插法,當兩個線程同時檢測到hashmap需要擴容,在進行同時擴容的時候有可能會造成鏈表的循環,主要原因就是,採用頭插法,新鏈表與舊鏈表的順序是反的,在1.8後採用尾插法就不會出現這種問題,同時1.8的鏈表長度如果大於8就會轉變成紅黑樹。

5. JDK1.8之後如何鏈地址法,鏈表長度是多少的時候會轉換成紅黑樹。

鏈表樹化需要滿足兩個條件:

1.鏈表長度大於等於 TREEIFY_THRESHOLD 初始值爲8
2.桶數組容量大於等於 MIN_TREEIFY_CAPACITY 初始值爲64

6. 節點個數是多少的時候,紅黑樹會退回鏈表。

8?這個存疑

7. 爲什麼會選擇8作爲鏈表轉紅黑樹的閾值。

計算出來的:通過源碼我們得知HashMap源碼作者通過泊松分佈算出,當桶中結點個數爲8時,出現的機率是億分之6的,因此常見的情況是桶中個數小於8的情況,此時鏈表的查詢性能和紅黑樹相差不多,因爲轉化爲樹還需要時間和空間,所以此時沒有轉化成樹的必要

8. HashMap與HashTable有什麼區別?

HashTable 使用 synchronized 來進行同步,線程安全。
HashMap 可以插入鍵爲 null 的 Entry。
HashMap 的迭代器是 fail-fast 迭代器。
HashMap 不能保證隨着時間的推移 Map 中的元素次序是不變的

9. 有沒有了解過ConcurrentHashMap?

10. JDK1.8之後ConcurrentHashMap如何保證線程安全性?(CAS+synchronized),這裏還順便問了synchronized和可重入鎖的區別。

1、不採用segment而採用node,鎖住node來實現減小鎖粒度。
2、設計了MOVED狀態 當resize的中過程中 線程2還在put數據,線程2會幫助resize。
3、使用3個CAS操作來確保node的一些操作的原子性,這種方式代替了鎖。
4、sizeCtl的不同值來代表不同含義,起到了控制的作用。
採用synchronized而不是ReentrantLock

11. 說到synchronized,說些synchronized加在static關鍵字前和普通方法前的區別?

線程八鎖問題,可看我的文章:線程八鎖

12. 看你熟悉單例,說下單例懶漢式和餓漢式的區別?(手寫)

https://blog.csdn.net/bupttulongming/article/details/103218282

13. 懶漢式下如何保證線程安全?

synchronized修飾 get方法

14. 創建線程安全的單例有那些實現方法?

餓漢式,類加載的時候就創建實例

15. 說一下JVM的內存模型?(每一個模塊都說)

公有的堆區方法區,私有的程序計數器,本地方法棧,虛擬機棧

16. 熟不熟悉垃圾回收算法?

GC算法主要有複製算法,標記清除算法,標記整理算法,適用於不同情況

17. 如何判定一個對象是否應該回收。

目前,Java 虛擬機判斷垃圾對象使用的是:GC Root Tracing 算法。其大概的過程是這樣:從 GC Root 出發,所有可達的對象都是存活的對象,而所有不可達的對象都是垃圾。

Gc-root:
虛擬機棧中引用的對象
方法區中類靜態屬性引用的對象
方法區中常量引用的對象
本地方法棧中JNI引用的對象

18. 除了垃圾回收,還有那些工作會造成CPU負載過高(其實這裏給出的是一個場景,就是讓描述一下除了垃圾回收之外,還有那些工作會讓線上CPU佔用到百分之90-100,並且給出排查過程。)。

代碼中複雜計算,用top指令查看佔用CPU高的進程,CPU問題排查流程

19. 說一下CMS垃圾回收器和G1收集器的特點,和收集過程。
  • CMS 收集器全稱爲 Concurrent Mark Sweep,意爲標記清除算法,其是一個使用多線程並行回收的垃圾收集器。獲取最短回收停頓時間爲目標

基於標記-清除算法實現。併發收集、低停頓。
適用於注重服務的響應速度,希望系統停頓時間最短的使用環境
主要工作步驟有:初始標記、併發標記、預清理、重新標記、併發清除和併發充值。其中初始標記和重新標記是獨佔系統資源的,而其他階段則可以和用戶線程一起執行。

  • G1收集器是整堆收集器

並行併發 :G1能充分利用多CPU、多核環境下的硬件優勢,使用多個CPU來縮短Stop-The-World停頓時間。部分收集器原本需要停頓Java線程來執行GC動作,G1收集器仍然可以通過併發的方式讓Java程序繼續運行。
分代收集:G1能夠獨自管理整個Java堆,使用了分區算法,從而使得 Eden 區、From 區、Survivor 區和老年代等各塊內存不必連續
空間整合 :G1運作期間不會產生空間碎片,收集後能提供規整的可用內存。

G1收集器分爲四個工作步驟:

新生代 GC
併發標記週期:在這個階段,所有將要被回收的區域會被 G1 記錄在一個稱之爲 Collection Set 的集合中。
混合收集:混合回收階段會首先針對 Collection Set 中的內存進行回收,因爲這些垃圾比例較高
Full GC:當在回收階段遇到內存不足時,G1 會停止垃圾回收並進行一次 Full GC,從而騰出更多空間進行垃圾回收

20. String a = “abc”;和String b = new String(“abc”);是不是一樣的?爲什麼?他們對應的內存空間分別是什麼?

不一樣,前者會去字符串常量池找有沒有abc這個對象,如果有賦值引用;利用new來創建字符串時,無論字符串常量池中是否有與當前值相同的對象引用,都會在堆中新開闢一塊內存,創建一個新的對象。如果算上棧的引用str

21. 說一下JVM創建對象的過程。

找了篇博客JVM對象創建過程

22. 說一下byte a = 127; byte b = 127; a+=b和a = a+b的區別分別會出現什麼問題。

+=操作符會進行隱式自動類型轉換

23. 是否熟悉mysql?說一下mysql的隔離級別和對應的問題。

本人的文章:關於mysql隔離級別和事務

24. 什麼是MVCC,主要是爲了做什麼?

這篇文章:MVCC介紹

25. 說一下Spring的IOC和AOP在項目裏是怎麼用的。

IOC比較多,依賴倒轉;AOP可能是日誌,安全這些部分

26. AOP的兩種實現方式,並且說一下哪一個效率更高一些,爲什麼。

cglib和jdk動態代理,,在1.6和1.7的時候,JDK動態代理的速度要比CGLib動態代理的速度要慢,但是並沒有教科書上的10倍差距,在JDK1.8的時候,JDK動態代理的速度已經比CGLib動態代理的速度快很多了

27. 說一些Spring的事務傳播機制。

本人文章有:https://blog.csdn.net/bupttulongming/article/details/101195079


總結

這份面經還是挺有難度的,MVCC,G1和CMS收集過程感覺之前沒複習過,挺細的

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