首頁 > 軟體

(小奇JAVA面試)每日10道Java面試題打卡—Java基礎篇2

2021-05-26 22:31:21
文章配圖

十一、HashMap和HashTable有什麼區別?其底層實現是什麼?

1、HashTable中每一個方法都加了鎖,所以他是執行緒安全的,但是由於每個方法都加了鎖,所以效率比較低,目前用的比較少。

2、HashMap允許Key和Value為null,而HashTable不允許。

3、底層實現:陣列+連結串列

4、jdk8開始連結串列高度到8、陣列長度超過64,連結串列轉為紅黑樹。

5、如果產生hash衝突,先進行equals比較,相同則取代該元素,不同,則判斷連結串列高度插入連結串列,連結串列高度達到8,並且陣列長度到64則轉變為紅黑樹,長度低於64則將紅黑樹轉為連結串列。

十二、ConcurrentHashMap原理,jdk7和jdk8版本的區別

ConcurrentHashMap和HashTable都是執行緒安全的,但是ConcurrentHashMap使用的是分段鎖,所以效率比HashTable高。

1、jdk7:資料結構:ReentrantLock+Segment+HashEntry,一個Segment中包含一個HashEntry陣列,每個HashEntry又是一個連結串列結構。

2、鎖:Segment分段鎖,Segment繼承了ReentrantLock,鎖定操作的Segment,其他的Segment不受影響,併發度為Segment個數,可以通過建構函式指定,陣列擴容不會影響其他的segment

3、元素查詢:二次hash,第一次Hash定位到Segment,第二次Hash定位到元素所在的連結串列的頭部。

4、get方法無需加鎖,volatile保證

5、jdk8:資料結構:synchronized+CAS+Node+紅黑樹,Node的val和next都用volatile修飾,保證可見性,查詢,替換,賦值操作都使用CAS

6、鎖:鎖鏈表的head節點,不影響其他元素的讀寫,鎖力度更細,效率更高,擴容時,阻塞所有的讀寫操作、併發、擴容。

7、讀操作無鎖:Node的val和next使用volatile修飾,讀寫執行緒對該變數互相可見,陣列用volatile修飾,保證擴容時被讀執行緒感知。

十三、如何實現一個IOC容器

1、配置檔案配置包掃描路徑

2、遞迴包掃描獲取.class檔案

3、反射、確定需要交給IOC管理的類

4、對需要注入的類進行依賴注入

十四、什麼是位元組碼?作用是什麼

1、我們平時寫完的程式碼是.java字尾的,我們通過編譯成.class檔案後就是位元組碼檔案,位元組碼是java虛擬機器可讀的。

2、作用:java是將源碼編譯為.class檔案,然後又通過虛擬機器解釋運行的,這樣解決了傳統解釋性語言執行效率低的問題,同時又保證瞭解釋型語言可移植的特點。

十五、Java類載入器有哪些

1、JDK自帶有三個類載入器:bootstrap ClassLoader(引導類載入器)、ExtClassLoader(擴展類載入器)、AppClassLoader(應用類載入器)。

2、bootstrap ClassLoader是EctClassLoader的父類載入器,預設載入lib下的jar包。

3、ExtClassLoader是AppClassLoader的父類載入器,負責載入lib/ext資料夾下的jar包。

4、AppClassLoader是應用類載入器,負責載入classpath下的類檔案。

十六、雙親委派模型

文章配圖

十七、Java中的異常有哪些

1、Java中的所有異常都來自頂級父類Throwable。

2、Throwable下有兩個子類Exception和Error。

3、Error是程式無法處理的錯誤,一旦出現這個錯誤,則程式將被迫停止運行。

4、Exception不會導致程式停止,又分為兩種,一個是RunTimeExcepion運行時異常,另一個是CheckedException檢查異常。

5、RunTimeException常常發生在程式運行過程中,會導致程式當前執行緒執行失敗,CheckedException常常發生在程式編譯過程中,會導致編譯不通過。

十八、GC如何判斷物件可以被回收

1、引用計數法:每個物件有一個引用計數屬性,新增一個引用時計數加1,引用釋放時計數減1,計數為0時可以回收。

2、可達性分析法:從GC Roots開始向下搜尋,搜尋所走過的路徑成為引用鏈,當一個物件到GC Roots沒有任何引用鏈相連時,則證明此物件時不可用的,那麼虛擬機器就判斷是可回收物件。

3、GC Roots的物件有:

1》虛擬機器棧中引用的物件(比如New User(),那麼這個User就是GC Roots)

2》方法區中類靜態屬性引用的物件

3》方法區中常量引用的物件

4》本地方法棧中引用的物件

十九、執行緒的生命週期,執行緒有哪些狀態

1、執行緒通常有五種狀態,創建、就緒、運行、阻塞和死亡狀態。

2、阻塞的情況又分為三種:

1》等待阻塞:運行的執行緒執行wait方法,該執行緒會釋放佔用的所有資源,JVM會把該執行緒放入「等待池」中,進入這個狀態後,是不能自動喚醒的,必須依靠其他執行緒呼叫notify或notifyAll方法才能被喚醒,wait是object類方法。

2》同步阻塞:運行的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,則JVM會把該執行緒放入「鎖池」中。

3》其他阻塞:運行的執行緒執行sleep或join方法,或者發出了I/O請求時,JVM會把該執行緒置為阻塞狀態,當sleep狀態超時、join等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入就緒狀態。sleep是Thread類的方法。

3、新建狀態(New):新創建了一個執行緒物件。

4、就緒狀態(Runnable):執行緒物件創建後,其他執行緒呼叫了該物件的start方法,該狀態的執行緒位於可運行執行緒池中,變得可運行,等待獲取cpu的使用權。

5、運行狀態(Running):就緒狀態的執行緒獲取了cpu,執行程式程式碼。

6、阻塞狀態(Blocked):阻塞狀態是執行緒因為某種原因放棄cpu使用權,暫時停止運行,直到執行緒進入就緒狀態,才有機會轉到運行狀態。

7、死亡狀態(Dead):執行緒執行完了或者因異常退出了run方法,該執行緒結束生命週期。

二十、sleep()、wait()、join()、yield()的區別

1、鎖池

所有需要競爭同步鎖的執行緒都會放在鎖池當中,比如當前物件的鎖已經被其中一個執行緒得到,則其他執行緒需要在這個鎖池進行等待,當前面的執行緒釋放同步鎖後鎖池中的執行緒去競爭同步鎖,當某個執行緒得到後會進入就緒佇列進行等待CPU資源分配。

2、等待池

當我們呼叫wait()方法後,執行緒會放到等待池當中,等待池的執行緒是不會去競爭同步鎖,只用呼叫了notify()或notifyAll()後等待池的執行緒才會開始去競爭鎖,notify()是隨機從等待池選出一個執行緒放到鎖池,而notifyAll()是將等待池的所有執行緒放到鎖池當中。

3、sleep是Thread類的靜態本地方法,wait則是Object類的本地方法。

4、sleep方法不會釋放lock,但是wait會釋放,而且會加入到等待佇列中。

5、sleep方法不依賴於同步器synchronized,但是wait需要依賴synchronized關鍵字。

6、sleep一般用於當前執行緒休眠,或者輪詢暫停操作,wait則多用於多執行緒之間的通訊。

7、sleep會讓出cpu執行時間且強制上下文切換,而wait則不一定,wait後可能還是有機會重新競爭到鎖繼續執行的。

8、yield()執行後執行緒直接進入就緒狀態,馬上釋放了cpu的執行權,但是依然保留了cpu的執行資格,所以有可能cpu下次進行執行緒排程還會讓這個執行緒獲取執行權繼續執行。

9、join()執行後執行緒進入阻塞狀態,例如線上程B中呼叫執行緒A的join(),那執行緒B會進入到阻塞佇列,直到執行緒A結束或中斷執行緒。


IT145.com E-mail:sddin#qq.com