被虐的有點慘的有贊Java面試解析
- 2019 年 10 月 4 日
- 筆記
之前自己寫了點面經,裡面只有題目,沒有答案,結果一個朋友說要針對這些題目做個解答,沒想過過了這麼久,終於看到發了出來了,於是就轉過來了,大家看看吧,雖說不一定就一定面試遇得到同樣的問題。
我的有贊面經,如果對面經感興趣,可以在公眾號裡面回復"面經"即可以看到更多我以前寫的。昨天的一面面試解析:Java 面試解析(有贊一面)
以下是朋友的文章,請閱讀。
本文的題目出自部落格 http://www.54tianzhisheng.cn/2018/07/12/youzan/
但是作者沒有給出答案,部落客斗膽來製作答案版。
引言
說在前面的話: 本文適合人群:急等著換工作的人 我承認刷面試題很有用的,縱觀幾年來的JAVA面試題,你會發現每家都差不多。比如,你仔細觀察,你會發現,HashMap的出現幾率未免也太高了吧!連考察的知識點都一樣,什麼hash碰撞啊,並發問題啊!再比如JVM,無外乎考記憶體結構,GC演算法等!因此,如果是為了面試,完全是有套路可以準備的!記住,基礎再好,也架不住面試官天馬行空的問,所以刷面試題還是很有必要的!
本文不適合人群:專攻JAVA某方面技術的人 因為這類人專攻JAVA某塊技術,知識容易出現死角。貿然閱讀本文,發現自己一堆題目都不會,會覺得有一種挫敗感,發現自己連校招生都不如。然而,會點面試題不算什麼,畢竟Homebrew作者也出現過解不出面試題,被Google拒絕,緣由就是,因為他不會翻轉二叉樹。難道你能說Homebrew的作者水平有問題!
正文
1、HashMap,源碼級別的問了,包括為什麼執行緒不安全 評註:這問題一面的時候問過了,嗯,說明大家以後面試,不管是幾面,複習過的知識點還是要複習,畢竟一面的面試官只會告訴二面的面試官印象,不會具體聊問了啥問題!比如,我和二面面試官說,這個候選人基礎還不錯,那二面面試官就會覺得:"咦,這個人基礎不錯,我試試是不是真的是這樣!"所以難免會出現一樣的題目! 另外,此題不好答。因為是關於源碼級別的問,需要複習的知識點很多。大家關注一下我,我會出一篇對HashMap能問的知識點總結。比如jdk1.7和jdk1.8的hashmap結構區別、hashmap並發問題,哈希衝突的常見解決手段等! 回答: 略去。
2、死鎖 評註:這問題一面的時候問過了,嗯,凸顯! 回答: 死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去,如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。
產生死鎖的原因主要是:
- 因為系統資源不足。
- 進程運行推進的順序不合適。
- 資源分配不當等。
3、Synchronized 和 ReentrantLock 鎖機制,怎麼判斷重入鎖的,會不會是死鎖? 評註:並發基礎問題,懂並發編程的,應該都會。 回答: 先答區別: API方面:synchronized既可以修飾方法,也可以修飾程式碼塊。ReentrantLock只能在方法體中使用。 公平鎖:synchronized的鎖是非公平鎖,ReentrantLock默認情況下也是非公平鎖,但可以通過帶布爾值的構造函數要求使用公平鎖。 等待可中斷:假如業務程式碼中有兩個執行緒,Thread1 Thread2。假設 Thread1 獲取了對象object的鎖,Thread2將等待Thread1釋放object的鎖。
- 使用synchronized。如果Thread1不釋放,Thread2將一直等待,不能被中斷。synchronized也可以說是Java提供的原子性內置鎖機制。內部鎖扮演了互斥鎖(mutual exclusion lock ,mutex)的角色,一個執行緒引用鎖的時候,別的執行緒阻塞等待。
- 使用ReentrantLock。如果Thread1不釋放,Thread2等待了很長時間以後,可以中斷等待,轉而去做別的事情。
至於判斷重入鎖,ReenTrantLock的字面意思就是再進入的鎖,其實synchronized關鍵字所使用的鎖也是可重入的,兩者關於這個的區別不大。兩者都是同一個執行緒沒進入一次,鎖的計數器都自增1,所以要等到鎖的計數器下降為0時才能釋放鎖。
4、進程和執行緒的區別? 評註:作業系統的題目,很常規! 回答: 進程:是執行中一段程式,即一旦程式被載入到記憶體中並準備執行,它就是一個進程。進程是表示資源分配的的基本概念,又是調度運行的基本單位,是系統中的並發執行的單位。
執行緒:單個進程中執行中每個任務就是一個執行緒。執行緒是進程中執行運算的最小單位。
一個執行緒只能屬於一個進程,但是一個進程可以擁有多個執行緒。多執行緒處理就是允許一個進程中在同一時刻執行多個任務。
執行緒是一種輕量級的進程,與進程相比,執行緒給作業系統帶來側創建、維護、和管理的負擔要輕,意味著執行緒的代價或開銷比較小。
5、進程之間如何保證同步? 評註:作業系統老題了,四種方法! 回答:上網給大家找了一張圖!

6、分散式鎖 評註:此題問的沒頭沒尾的,分散式鎖可以問的點很多,比如實現方式啊?性能差距啊? 回答:這題如果要詳答,看我的另一篇文章《分散式之抉擇分散式鎖》 分散式鎖有三種實現方式:資料庫、快取、Zookeeper,這裡我直接羅列一下各種鎖的對比吧
從理解的難易程度角度(從低到高) 資料庫 > 快取 > Zookeeper
從實現的複雜性角度(從低到高) Zookeeper >= 快取 > 資料庫
從性能角度(從高到低) 快取 > Zookeeper >= 資料庫
從可靠性角度(從高到低) Zookeeper > 快取 > 資料庫
7、對象 GC 評註:一面問過,把一面的回答貼過來! 回答: 這個演算法的基本思路是通過一些列稱為「GC Roots」的對象作為起始點,從這些點開始向下搜索,搜索走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,則證明對象需要被回收. 如圖:

上圖中o3,o4對象沒有任何GC Roots可達到,所有這兩個對象不可用了,需要被GC回收 Java可作為GC Roots的對象包括下面幾種:
- 虛擬機棧中引用的對象
- 方法區中類靜態屬性引用的對象
- 方法區中產量引用的對象
- 本地方法棧中JNI引用的對象
8、垃圾回收演算法 評註:一面問過,把一面的回答貼過來! 回答: 標記-清除演算法、標記整理演算法、複製演算法、分代收集演算法
9、JVM 參數 評註:這個回答還是略去吧,這個問題範圍太大,我不知道該怎麼答。 回答:略去。
10、OOM 出現的有哪些場景?為什麼會發生? 評註:常規題,只是情況太多了! 回答: OOM for Heap (java.lang.OutOfMemoryError: Java heap space):heap的最大值不滿足需要,將設置heap的最大值調高即可。 OOM for StackOverflowError (Exception in thread "main" java.lang.StackOverflowError):如果執行緒請求的棧深度大於虛擬機所允許的最大深度,將拋出StackOverflowError異常。 OOM for GC (java.lang.OutOfMemoryError: GC overhead limit exceeded):此OOM是由於JVM在GC時,對象過多,導致記憶體溢出。 OOM for native thread created (java.lang.OutOfMemoryError: unable to create new native thread):這個異常問題本質原因是我們創建了太多的執行緒,而能創建的執行緒數是有限制的,導致了異常的發生。 OOM for allocate huge array (Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit):此類資訊表明應用程式試圖分配一個大於堆大小的數組。例如,如果應用程式new一個數組對象,大小為512M,但是最大堆大小為256M,因此OutOfMemoryError會拋出,因為數組的大小超過虛擬機的限制。 OOM for small swap (Exception in thread "main": java.lang.OutOfMemoryError: request bytes for . Out of swap space? ):拋出這類錯誤,是由於從native堆中分配記憶體失敗,並且堆記憶體可能接近耗盡。 OOM for exhausted native memory (java.lang.OutOfMemoryErr java.io.FileInputStream.readBytes(Native Method)):由於Native memory被耗盡導致的。
11、JVM 記憶體結構說下吧 評註:常規題,學過JVM的都會! 回答:來一張圖就好了。 有5大記憶體區域,按照是否被執行緒所共享可分為兩部分,一部分是執行緒獨佔區域,包括Java棧,本地方法棧和程式計數器。還有一部分是被執行緒所共享的,包括方法區和堆。注意了,下一題就是問的是堆和棧的共享問題! 如下圖所示

12、堆和棧的共享問題? 評註:常規題,大家應該都答的上來,屬應屆生常見問題! 回答: 棧記憶體的一個特點是數據共享,比如你執行緒中執行下面兩句話
int i = 1; int j = 1;
如下圖所示

前面定義了i=1,i和1都在棧記憶體內,如果再定義一個j=1,此時將j放入棧記憶體,然後查找棧記憶體中是否有1,如果有則j指向1。 堆記憶體沒有數據共享的特點,比如你執行緒中執行了下面兩句話
String s = new String( "Hello World" ); String w = new String( "Hello World" );
此時如下圖所示

13、有比較過 Http 和 RPC 嗎? 評註:此題我按我的理解來答。我不確定對不對,因此我覺得http和rpc沒啥可比性,不是一個級別的概念。 回答: 只要是遠程調用都可以叫RPC,和是不是通過http沒什麼關係。 那麼,調用過程,也就是通訊過程之間需要協議,可以是HTTP協議、dubbo協議等、其他協議等。
14、HttpClient 你說說裡面的具體實現吧?(涉及了哪些東西) 評註:此題只能回答一個大概,我找了一個架構圖來進行說明 回答: 如下圖所示

Httpclient將對接的伺服器或者集群(相同域名)稱為route,並為每個route建立若干連接,並池化在連接池裡。Client通過tcp/ip協議發送請求以及接受應答,在發送請求前和接收應答後都會經由interceptor進行鏈式處理,在httpclient里這些interceptor被稱為HttpProcessor,負責處理諸如設置報文頭,報文體,編碼格式等以及解析報文頭,報文體,解碼格式等http規範報文格式範疇內的事情。
15、那要你設計一個高性能的 Http ,你會怎麼設計? 評註:此題,作者漏了最重要的主語。。。Http什麼?Http伺服器么?HTTP介面?此題範圍太大,都可以單獨寫文章了。可以關注作者,後面寫。 回答:略去