1. 程式人生 > >21道最新Java面試題剖析(資料庫+JVM+微服務+高併發)

21道最新Java面試題剖析(資料庫+JVM+微服務+高併發)

前言

縱觀幾年來的Java面試題,你會發現每家都差不多。你仔細觀察就會發現,HashMap的出現機率未免也太高了吧!連考察的知識點都一樣,什麼hash碰撞啊,併發問題啊!再比如JVM,無外乎考記憶體結構,GC演算法等!因此,如果是為了面試,完全是有套路可以準備的!記住,基礎再好,也架不住面試官天馬行空的問,所以刷面試題還是很有必要的!

 

面試題解析

1、Map 的底層結構?(HashMap)

評註:老題目了,各位面試的人員必須熟記!

回答:Map是以鍵值對來儲存物件的,它的底層實際上是陣列和連結串列來組成的,經典的一張圖如下(別人畫的);

 

當使用put方法時,先查找出陣列位置是否存在物件,通過key.hashcode對陣列長度取餘;存在,則把裡面的連結串列拿出來,判斷連結串列裡面是否存在key值與傳遞過來的key值一樣的物件,存在,則把傳遞過來的value取代連結串列key對應的value,不存在,則直接通過連結串列的add()方法加到連結串列後面;

當使用get方法時,先查找出陣列位置是否存在物件,通過key.hashcode對陣列長度取餘;如果不存在,則返回為空,如果存在,則遍歷連結串列,判斷連結串列裡面是否存在key值與傳遞過來的key值一樣的物件,存在,則把key值對應的value取出返回,不存在,則返回為空;

2、執行緒安全的 Map (concurrentHashMap)簡單的說了下這兩 1.7 和 1.8的區別,本想問下要不要深入的講下(原始碼級別),結果面試官說不用了。

評註:老題目了,如果有時間,再去了解一下,解決HashMap執行緒安全的各種方法,以及原理!此題只能大概回答一下結構的變化,因為其中的實現程式碼都變了,細說可以說很久,估計面試官也沒時間聽!

回答:

jdk1.7中採用 Segment + HashEntry的方式進行實現,結構如下:

 

Segment陣列的意義就是將一個大的table分割成多個小的table來進行加鎖,而每一個Segment元素儲存的是HashEntry陣列+連結串列,這個和HashMap的資料儲存結構一樣

而jdk1.8中則

去除 Segment + HashEntry + Unsafe 的實現,

改為 Synchronized + CAS + Node + Unsafe 的實現

其結構圖如下:

 

如上圖所示,取消了Segment欄位,陣列中儲存的就是Node。它與HashMap中的HashEntry定義很相似,但是有一些差別。它對value和next屬性設定了volatile同步鎖,它不允許呼叫setValue方法直接改變Node的value域。

另外,將原先table陣列+單向連結串列的資料結構,變更為table陣列+單向連結串列+紅黑樹的結構,在hash碰撞過多的情況下會將連結串列轉化成紅黑樹。

3、專案 MySQL 的資料量和併發量有多大?

評註:此題為走向題,你的回答不同,後面問題走向就變了。

關於容量:單錶行數超過 500 萬行或者單表容量超過2GB,此時就要答分庫分表的中介軟體了!那後面題目的走向就變為mycat、sharing-jdbc等分庫分表中介軟體的底層原理了!

關於併發量:如果併發數過1200,此時就要答利用MQ或者redis等中介軟體,作為補償措施,而不能直接操作資料庫。那後面的題目走向就是redis、mq的原理了!

介於面試者還是一個應屆生,我斗膽猜測面試者是這麼答的

回答:資料量估計就三四百萬吧,併發量就五六百左右!

4、你對資料庫瞭解多少?

評註:因為你答的資料量和併發量不大,因此中介軟體這塊沒啥好問的。因此,題目走向變為資料庫底層!另外,此題為引導題,面試官在給你機會引向你最擅長的方面!

回答:瞭解常見資料庫調優方法,索引優化等!

5、你說下資料庫的索引實現和非主鍵的二級索引

評註:這個問題是根據上面,你的回答而問出來的!記得引向自己最擅長的資料庫基礎知識!預設是回答mysql資料庫的

回答:

從資料結構角度:

B-Tree索引,資料結構就是一顆B+樹。

Hash索引,Hash索引比較的是進行Hash運算之後的Hash值,所以它只能用於等值的過濾,不能用於基於範圍的過濾。基本不用!

R-Tree索引,僅支援geometry資料型別,也基本不用!

至於非主鍵的二級索引,這個實際上問的就是非聚簇索引!非聚簇索引本身就是一顆B+樹,其根節點指向聚簇索引的B+樹。

6、專案用的是 SpringBoot ,你能說下 Spring Boot 與 Spring 的區別嗎?

評註:基礎題,會spring boot的,基本都答的上來。就算沒準備過,當場思考下都可以回答的出來!也是屬於引導題!

回答:

  • Spring Boot可以建立獨立的Spring應用程式;
  • 內嵌瞭如Tomcat,Jetty和Undertow這樣的容器,也就是說可以直接跑起來,用不著再做部署工作了。
  • 無需再像Spring那樣搞一堆繁瑣的xml檔案的配置;
  • 可以自動配置Spring;
  • 提供了一些現有的功能,如量度工具,表單資料驗證以及一些外部配置這樣的一些第三方功能;
  • 提供的POM可以簡化Maven的配置

7、SpringBoot 的自動配置是怎麼做的?

評註:此題也是根據你的第七問,進一步提問而得出。

回答:

先答為什麼需要自動配置?

顧名思義,自動配置的意義是利用這種模式代替了配置 XML 繁瑣模式。以前使用 Spring MVC ,需要進行配置元件掃描、排程器、檢視解析器等,使用 Spring Boot 自動配置後,只需要新增 MVC 元件即可自動配置所需要的 Bean。所有自動配置的實現都在 spring-boot-autoconfigure 依賴中,包括 Spring MVC 、Data 和其它框架的自動配置。

接著答spring-boot-autoconfigure 依賴的工作原理?

spring-boot-autoconfigure 依賴的工作原理很簡單,通過 @EnableAutoConfiguration 核心註解初始化,並掃描 ClassPath 目錄中自動配置類對應依賴。比如工程中有木有新增 Thymeleaf 的 Starter 元件依賴。如果有,就按按一定規則獲取預設配置並自動初始化所需要的 Bean。

其實還能再繼續答@EnableAutoConfiguration 註解的工作原理!不過篇幅太長,答到上面那個地步就夠了!

8、MyBatis 定義的介面,怎麼找到實現的?

評註:mybatis底層原理題,考察有沒有看過mybatis的原理。博主剛好曾經自己寫過一個mybatis,所以此題恰巧答的上來。

博主內心活動:"現在校招的都這麼牛逼了麼!"

回答:一共五步

  • 1. Mapper 介面在初始SqlSessionFactory 註冊的。
  • 2. Mapper 介面註冊在了名為 MapperRegistry 類的 HashMap中, key = Mapper class value = 建立當前Mapper的工廠。
  • 3. Mapper 註冊之後,可以從SqlSession中get
  • 4. SqlSession.getMapper 運用了 JDK動態代理,產生了目標Mapper介面的代理物件。
  • 5. 動態代理的 代理類是 MapperProxy ,這裡邊最終完成了增刪改查方法的呼叫。

9、Java 記憶體結構

評註:基礎題,這個應該學JAVA的都會吧!送分題!如果博主沒理解錯應該是在問JVM的記憶體結構!

回答:JVM記憶體結構主要有三大塊:堆記憶體、方法區和棧。堆記憶體是JVM中最大的一塊由年輕代和老年代組成,而年輕代記憶體又被分成三部分,Eden空間、From Survivor空間、To Survivor空間,預設情況下年輕代按照8:1:1的比例來分配;

方法區儲存類資訊、常量、靜態變數等資料,是執行緒共享的區域,為與Java堆區分,方法區還有一個別名Non-Heap(非堆);棧又分為java虛擬機器棧和本地方法棧主要用於方法的執行。

10、物件是否可 GC?

評註:這個問題就是在問,JVM如何判斷物件是否需要被回收!不用答引用計數法,答可達性分析演算法就行。

回答:

這個演算法的基本思路是通過一些列稱為“GC Roots”的物件作為起始點,從這些點開始向下搜尋,搜尋走過的路徑稱為引用鏈,當一個物件到GC Roots沒有任何引用鏈相連時,則證明物件需要被回收.

如圖:

 

上圖中o3,o4物件沒有任何GC Roots可達到,所有這兩個物件不可用了,需要被GC回收

Java可作為GC Roots的物件包括下面幾種:

  • 虛擬機器棧中引用的物件
  • 方法區中類靜態屬性引用的物件
  • 方法區中產量引用的物件
  • 本地方法棧中JNI引用的物件

11、Minor GC 和 Full GC

評註:基礎題,會JVM調優的,基本都會!我只是奇怪,怎麼沒問Major GC呢?我們還是把Major GC也給答了吧!

回答:

堆記憶體是JVM中最大的一塊由年輕代和老年代組成。

那麼,從年輕代空間(包括 Eden 和 Survivor 區域)回收記憶體被稱為 Minor GC。

Major GC 是清理老年代。

Full GC 是清理整個堆空間—包括年輕代和老年代。

12、垃圾回收演算法

評註:基礎題,博主斗膽猜測,應該是在問垃圾回收演算法有哪些。面試官應該沒有耐心去聽你一個個去背演算法概念!

回答:

標記-清除演算法、標記整理演算法、複製演算法、分代收集演算法

13、垃圾回收器 G1

評註:上面的題目更深入的問法。JVM可以配置不同的回收器。比如Serial, Parallel和CMS幾種垃圾回收器。以Serial Collector(序列回收器)為例,它在在年輕代是一個使用標記-複製演算法的回收器。在老年代使用的是標記-清掃-整理演算法。

另外,關於G1回收器可以問的點很多,此題作者沒有描述清楚究竟問的是G1回收器的那個點,就滿回答一下概念吧!

如果是我來問,我就直接給你場景,問你該用哪種回收器了。直接問回收器,那就比較容易了!

常用引數:

-XX:+UseSerialGC:在新生代和老年代使用序列收集器

-XX:+UseParNewGC:在新生代使用並行收集器

//自己查詢吧,太多了!

回答:

G1 GC是Jdk7的新特性之一、Jdk7+版本都可以自主配置G1作為JVM GC選項。G1 將整個堆劃分為一個個大小相等的小塊(每一塊稱為一個region),每一塊的記憶體是連續的,每個塊也會充當 Eden、Survivor、Old三種角色,但是它們不是固定的,這使得記憶體使用更加地靈活。如下圖所示

 

執行垃圾收集時,收集執行緒在標記階段和應用程式執行緒併發執行,標記結束後,G1 也就知道哪些區塊基本上是垃圾,存活物件極少,G1 會先從這些區塊下手,因為從這些區塊能很快釋放得到很大的可用空間,這也是為什麼 G1 被取名為 Garbage-First 的原因。 加q群:478052716 免費領取(Java架構資料,視訊資料,BATJ面試資料)

14、專案裡用過 ElasticSearch 和 Hbase,有深入瞭解他們的調優技巧嗎?

評註:一個應屆生搭的ElasticSearch 和 Hbase,一般都只是demo級別的,懂基本的CRUD的使用即可!一般不會去深入瞭解調優技巧的!這個問題如果答深入瞭解過,是給自己挖坑!因為這個問題,答案太廣了!

回答:並沒有深入瞭解過!

15、Spring RestTemplate 的具體實現

評註:這題問的博主有點懵!如果是我來問,我會先問訪問Rest服務的客戶端這麼多,為什麼選Spring RestTemplate?然後才來原理。這個突然就冒出一個具體實現,我是有點懵啦!

回答:

其實RestTemplate和sl4fj這種門面框架很像,本質就是在Http的網路請求中增加一個馬甲,本身並沒有自己的實現。

底層可以支援多種httpclient的http訪問,上層為ClientHttpRequestFactory介面類,底層如下所示:

 

那麼RestTemplate則封裝了組裝、傳送 HTTP訊息,以及解析響應的底層細節。

答到這個份上可以了,難道你還要把類之間關係的引用圖,畫出來?太不現實了!

16、描述下網頁一個 Http 請求,到後端的整個請求過程

評註:基礎題,感覺屬於常識題!必會!

回答:

利用DNS進行域名解析 --> 發起TCP的3次握手 --> 建立TCP連線後發起http請求 --> 伺服器響應http請求,瀏覽器得到html程式碼 --> 瀏覽器解析html程式碼,並請求html程式碼中的資源(如js、css、圖片等) --> 瀏覽器對頁面進行渲染呈現給使用者

17、多執行緒的常用方法和介面類及執行緒池的機制

評註:基礎題,基本會點執行緒知識的,多多少少都會答點!但是這道題,我感覺範圍有點大啊!可能是作者沒表述清楚吧!

回答:

常用方法:

start,run,sleep,wait,notify,notifyAll,join,isAlive,currentThread,interrupt

常用介面類:

Runnable、Callable、Future、FutureTask

執行緒池的機制:

在面向物件程式設計中,建立和銷燬物件是很費時間的,因為建立一個物件要獲取記憶體資源或者其它更多資源。所以提高服務程式效率的一個手段就是儘可能減少建立和銷燬物件的次數,所以出現了池化技術!。

簡單的執行緒池包括如下四個組成部分即可:

  • 執行緒池管理器(ThreadPoolManager):用於建立並管理執行緒池
  • 工作執行緒(WorkThread): 執行緒池中執行緒
  • 任務介面(Task):每個任務必須實現的介面,以供工作執行緒排程任務的執行
  • 任務佇列:用於存放沒有處理的任務。提供一種緩衝機制

18、總結我的 Java 基礎還是不錯,但是一些主流的框架原始碼還是處在使用的狀態,需要繼續去看原始碼

評註:坦白說,我沒看出來哪些問題體現出主流的框架還是處在使用的狀態。

19、死鎖

回答:

死鎖是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去,如果系統資源充足,程序的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。

產生死鎖的原因主要是:

  • (1) 因為系統資源不足。
  • (2) 程序執行推進的順序不合適。
  • (3) 資源分配不當等。

20、自己研究比較新的技術,說下成果!

評註:嗯,凸顯自己的潛力,大家自由發揮!

21、你有什麼想問的?我就問了下公司那邊的情況,這個自