java面試(進階五篇)解答
題目來自於網路,答案是筆者整理的。僅供參考,歡迎指正
一、Java相關
-
樂觀悲觀鎖的設計,如何保證原子性,解決的問題;
-
char和double的位元組,以及在記憶體的分佈是怎樣;
-
物件記憶體佈局,然後講下物件的死亡過程?
-
物件頭,詳細講下;
-
sync原理詳細,sync內拋異常會怎樣,死鎖嗎?還是釋放掉?怎麼排查死鎖?死鎖會怎樣?有沒有什麼更好的替代方案?
-
詳細講一下集合,HashSet原始碼,HashMap原始碼,如果要執行緒安全需要怎麼做?
-
多執行緒是解決什麼問題的?執行緒池解決什麼問題?
-
執行緒池,如何設計的,裡面的引數有多少種,裡面的工作佇列和執行緒佇列是怎樣的結構,如果給你,怎樣設計執行緒池?
-
AQS原理,ReentranLock原始碼,設計原理,整體過程。
-
繼續聊多執行緒原始碼,sync原理,然後一個場景設計題;
-
float f = 1.4f;double d = 1.4d; 與 float f = 1.5f;double d = 1.5d; 是否為true,記憶體是怎樣的;
-
split的原始碼,split("a|b|c");得出多少個數組;
-
把所有認識熟用的JUC( java.util.concurrent(簡稱JUC)包)下的類寫出來,講下使用,然後講下原生的執行緒操作;
-
開閉原則,解析工廠方法模式,建造者模式,區別。手擼出來。
-
講下JVM的大頁模式,JVM記憶體模型;
-
什麼是敏捷開發,防禦性程式設計,並行程式設計。Team Leader的思考;
-
逃逸分析是什麼,作用是什麼,用途是什麼;
-
怎麼認為一個類是執行緒安全?執行緒安全的定義是什麼?Java有多少個關鍵字進行同步?為什麼這樣設計?(聊了一大堆,一堆為什麼);
-
兩個執行緒設計題。記得一個是:t1,t2,t3,讓t1,t2執行完才執行t3,原生實現。
-
寫個字尾表示式,為什麼要設計字尾表示式,有什麼好處?然後寫下中綴。
-
我看你做過效能優化,比如你怎麼分析專案裡面的OOM的,記憶體洩露呢?詳細說思路;
-
說下多執行緒,我們什麼時候需要分析執行緒數,怎麼分析,分析什麼因素;
-
抽象方法和類方法的區別,static的抽象方法可以嗎?
-
說下Java的克隆體系;
-
涉及OOM、JVM優化、原始碼問題、資料庫優化、多執行緒等問題;
-
CPU高?什麼情況CPU高?解決什麼問題?
-
你有遇到過臨界區問題嗎?有遇到過嗎?你在專案遇到這個問題是怎樣解決的?
-
volatile關鍵字作用;
-
Java的多型怎麼實現;
-
解釋一下自旋;
-
解釋一下訊號量;
-
什麼情況下會觸發類載入;
-
Java記憶體抖動嚴重,優化的思路;
二、資料庫相關
-
SQL優化思路,聯合索引與底層樹結構的映像關係,索引結構(B+、B-),為什麼用這樣的結構;
-
講下MySQL的叢集?叢集遇到過什麼問題?sql的優化?
-
你目前為止遇到的最大資料量是多少?知道100萬時候怎麼設計嗎?1000萬呢?過幾十億呢?
-
MySQL有多少個引數可調,除了最大連線數。全部列出來,一個個分析。
-
聊下優化過的索引,怎麼優化;
-
紅黑樹和平衡樹的區別,為什麼資料庫不用紅黑樹;
-
mysql有哪些鎖,意向鎖有什麼用;
-
資料庫高併發下的優化思路;
-
資料庫什麼情況下索引會失效;
三、資料結構和作業系統相關
-
資料結構學過吧,聊一下?學過什麼結構?講下樹和佇列?B樹呢?
-
作業系統學過吧,聊一下?講一下系統記憶體是怎樣的?分段分頁虛擬記憶體?
-
頁面置換演算法呢?多少種?有最優的置換演算法嗎?
-
你學過什麼課程?然後聊下作業系統,核心、使用者之類。
-
反轉連結串列手擼;
-
快排,給一串陣列,把具體每次patition寫下,最終結果也寫45, 32, 41, 35, 38, 20, 50;
-
一個整數status, 判斷第K個位元位是否為位元1;
-
把遞迴實現的快排改成非遞迴,你知道非遞迴有什麼好處嗎;
-
舉例使用分治思想的演算法;
四、網路相關
-
講下請求頭細節?
-
Http和Https?Http1.0,1.1,2.0,講下長連線和短連線?Https是怎樣的?如果我篡改了公鑰呢?怎麼防止?
-
Get和Post,講下區別,要我模擬出抓包來。
-
詳細講下Cookie和Session,Token,OAuth2.0協議;
-
擁塞演算法知道嗎?哪些,分別怎樣?
-
學過計算機網路是吧?socket熟悉嗎?對它的讀寫緩衝區有理解嗎?怎麼的?那滑動視窗是怎樣的?為什麼這樣設計?
-
再聊下Http的Http basic authentication;
-
Https的過程;
五、框架相關
-
聊下Spring原始碼,知道多少,都聊一下;
-
聊下Spring註解,@Autowire,@Resource,以及他們的解析過程;
-
聊一下架構,接入層架構,服務層架構。聊下技術棧,Spring Boot,Spring Cloud、Docker;
-
Spring ioc的具體優勢,和直接New一個物件有什麼區別;
-
Servlet生命週期,是否單例,為什麼是單例;
-
Spring Mvc初始化過程;
五、分散式相關
-
多少種RPC框架?
-
一致性雜湊是幹嘛的?
-
搭建高併發高可用系統需要怎樣設計?考慮哪些東西,有多少說多少。
-
你對快取有什麼理解?快取是解決什麼問題?後端快取有哪些,分別解決什麼問題?
-
聊一下分散式鎖;
-
你是怎麼設計系統快取的,為什麼,什麼場景;
-
也來說下,削峰的多種實現,Redis?MQ?
-
為什麼用mq就能削峰?解決什麼問題?
六、設計題
-
有幾臺機器儲存著幾億淘寶搜尋日誌,你只有一臺2g的電腦,怎麼選出搜尋熱度最高的十個搜尋關鍵詞;
-
如何設計演算法壓縮一段URL;
-
有一個頁面能同時展示兩個廣告,現在有五個廣告,設計演算法使五個廣告展示概率為1:2:3:4:5;
-
有25匹馬,五個賽道,用最少比賽次數將25匹馬排序;
七、其他相關
-
Tomcat快取,聊下快取的整體理解,知道多少種快取;
-
解釋下Mucene原理,倒排索引,怎樣進行中文分詞,基於什麼進行分詞;
-
TopN的大資料量題;
-
你對接入層要思考什麼東西?遇到過哪些問題?搭建系統要考量哪些因素?
-
然後專案問題,優化問題;
-
熟悉maven是吧?我們來聊下Maven的原始碼原理,Maven衝突的時候,怎麼選擇依賴包,我們怎麼查,我們遇到兩個不一樣的版本,我們應該如何去選擇,為什麼?
-
專案如何分組,效能優化小組應該做哪些;
-
我們來說下接入層的搭建,認知分析;
-
問下專案的系統構建,思考,為什麼這樣構建?
-
如何判斷一段程式碼的好壞;
參考答案
一、Java相關
1.樂觀悲觀鎖的設計,如何保證原子性,解決的問題;
悲觀鎖:總是假設最壞的情況,每次拿資料的時候都會以為別人會修改資料,所以拿資料時會上鎖。java中synchronized就是一個悲觀鎖的實現
樂觀鎖:每次拿資料的時候並不會上鎖,但是會在更新的時候判斷是否已經有別人已經更新資料。樂觀鎖適用於多讀的情況,這樣可以提高吞吐量。java.util.concurrent.atomic包下的原子變數類就是使用了樂觀鎖的一種方式(CAS)
2.char和double的位元組,以及在記憶體的分佈是怎樣
char:1byte
double:8byte
char和double都是基本型別,所以並不會像物件型別那樣,有物件頭和對其填充,所以在記憶體中也是佔用1byte和8byte
3.物件記憶體佈局,然後講下物件的死亡過程
物件在記憶體中的佈局主要分為三個塊:
* 物件頭(header)
* MarkWord(儲存物件自身的執行時資料,如:雜湊碼、GC年齡分代、鎖狀態標誌、執行緒持有的鎖、偏向執行緒ID、偏向時間戳等。32和64位虛擬機器分別使用32和64個bit)
* 型別指標(物件指向它的類的元資料的指標,JVM通過這個指標來確定這個物件是哪個類的例項)
* 例項資料(instance data)
* 對齊填充(padding)
物件的死亡過程:
4.物件頭,詳細講下
物件頭包括兩部分:
* MarkWord(主要是物件執行時的自身資料,雜湊碼、執行緒持有的鎖等資訊)
* 型別指標(指向物件所屬類元資料的指標)
5.sync原理詳細,sync內拋異常會怎樣,死鎖嗎?還是釋放掉?怎麼排查死鎖?死鎖會怎樣?有沒有什麼更好的替代方案
* Monitor:是一個同步工具,相當於作業系統中的互斥量(mutex),即值為1的訊號量。它內置於每個Object中,相當於一個許可證,拿到許可證即可操作,沒有則需要阻塞等待
* synchronized原理:
synchronized的同步程式碼塊在位元組碼引擎中執行時,其實是通過鎖物件的monitor的使用與釋放來實現的。
由於一個物件的monitor是唯一的,所以未獲取物件monitor的執行緒需要阻塞等待。
sync拋異常會釋放掉鎖;
排查死鎖可以通過jstack pid來檢視棧資訊,死鎖執行緒會展示為dead lock;
更好的替代方案是:可以使用ReentrantLock.tryLock等方法
6.詳細講一下集合,HashSet原始碼,HashMap原始碼,如果要執行緒安全需要怎麼做
原始碼可參考之前的解答方案
執行緒安全需要:採用HashTable獲取ConcurrentHashMap;CopyOnWriteArraySet等執行緒安全類
7.多執行緒是解決什麼問題的?執行緒池解決什麼問題?
多執行緒:在單執行緒情況下(也就是隻有main執行緒執行),任務是順序執行的,執行效率較低,無法利用CPU多核特性;如果一個任務發生阻塞,其他任務都無法執行;使用多執行緒執行的時候,可以充分利用CPU多核的特性,將任務執行變成並行的,執行效率更高
執行緒池:執行緒的建立和銷燬是需要作業系統配合的高階操作,是一種高開銷的操作。所以我們使用執行緒池來回收已經使用完成的執行緒,合理利用執行緒資源
8.執行緒池,如何設計的,裡面的引數有多少種,裡面的工作佇列和執行緒佇列是怎樣的結構,如果給你,怎樣設計執行緒池?
有關於ThreadPoolExecutor的構造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
* Executors.newSingleThreadExecutor() 工作佇列:LinkedBlockingQueue
* Executors.newCacheThreadPool() 工作佇列:SynchronousQueue ,執行緒池執行緒數量>corePoolSize,若執行緒有60秒的空閒時間,超過這個時間則回收
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
* Executors.newFixedThreadPool() 工作佇列:LinkedBlockingQueue
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
* Executors.newScheduledThreadPool() 工作佇列:DelayWorkQueue,
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
9.AQS原理,ReentranLock原始碼,設計原理,整體過程
具體可參考:https://www.cnblogs.com/chengxiao/p/7141160.html
10.繼續聊多執行緒原始碼,sync原理,然後一個場景設計題
參考5
11.float f = 1.4f;double d = 1.4d; 與 float f = 1.5f;double d = 1.5d; 是否為true,記憶體是怎樣的;
不明白什麼叫是否為true;
由於是基本型別,float佔用4byte,double佔用8byte
12.split的原始碼,split("a|b|c");得出多少個數組
?
13.把所有認識熟用的JUC( java.util.concurrent(簡稱JUC)包)下的類寫出來,講下使用,然後講下原生的執行緒操作
併發類:
Executors
CountDownLatch
CyclicBarrier
ReentrantLock
ReentrantReadWriteLock
原子類:
AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicLong
AtomicLongArray
AtomicReference
容器類:
ArrayBlockingQueue
CopyOnWriteArrayList
LinkedBlockingQueue
LinkedBlockingDeque
CopyOnWriteArraySet
ConcurrentSkipListSet
ConcurrentHashMap
ConcurrentSkipListMap
14.開閉原則,解析工廠方法模式,建造者模式,區別。手擼出來
開閉原則:對擴充套件開放,對修改關閉
15.講下JVM的大頁模式,JVM記憶體模型
JVM記憶體模型:
JVM大頁模式 具體可參考:https://blog.csdn.net/zero__007/article/details/52926366
16.什麼是敏捷開發,防禦性程式設計,並行程式設計。Team Leader的思考
敏捷開發:https://www.sohu.com/a/157053455_590354
防禦性程式設計:https://www.cnblogs.com/bakari/archive/2012/08/27/2658215.html
並行程式設計:
17.逃逸分析是什麼,作用是什麼,用途是什麼
逃逸分析是目前JVM中比較前沿的優化技術
逃逸分析的基本行為就是分析物件動態作用域:
* 當一個物件在方法中被定義後,他有可能被外部方法所引用,例如作為呼叫引數傳遞到其他地方中,稱為方法逃逸
* 甚至有可能被外部執行緒訪問到,比如賦值給類變數或可以在其他執行緒中訪問的例項變數,稱為執行緒逃逸
如果證明一個物件不會逃逸到方法或執行緒外,則可以為這個變數進行一些高效優化,優化方案如下:
* 棧上分配(把方法中的變數和物件分配到棧上,方法執行完之後自動銷燬,不需要垃圾回收的介入,從而提高系統性能)
* 同步消除(執行緒物件同步本身比較消耗,如果確定一個執行緒不會被其他執行緒訪問到,那麼該物件的讀寫就不會存在競爭,對這個變數的同步措施就可以取消掉)
* 標量替換(JVM中的原始資料型別都不能再進一步分解,它們被稱為標量;如果一個數據可以繼續分解,那它稱為聚合量,物件就是聚合量。如果逃逸分析證明一個物件不會被外部訪問並且這個物件是可分解的,那程式真正執行的時候可能不會建立這個物件,而是直接建立它的若干個被這個方法訪問到的成員變數來替代)
18.怎麼認為一個類是執行緒安全?執行緒安全的定義是什麼?Java有多少個關鍵字進行同步?為什麼這樣設計?
執行緒安全:當多個執行緒訪問該類,這個類的方法始終表現為正確的行為,那麼可稱這個類執行緒安全
關鍵字:synchronized、ReentrantLock、ReentrantReadWriteLock、volatile(可見性非原子性)
19.兩個執行緒設計題。記得一個是:t1,t2,t3,讓t1,t2執行完才執行t3,原生實現
使用Thread.join方法
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
更多執行緒設計題可參考: https://blog.csdn.net/qq_26323323/article/details/83750198
20.寫個字尾表示式,為什麼要設計字尾表示式,有什麼好處?然後寫下中綴
如我們正常表示式為:a+b-c
如果變成字尾表示式:ab+c-
字尾表示式的好處,就是我們在設計表示式的計算模型的時候,如果將表示式設計為字尾的,那麼可以使用棧來快速的實現計算
21.我看你做過效能優化,比如你怎麼分析專案裡面的OOM的,記憶體洩露呢?詳細說思路
22.說下多執行緒,我們什麼時候需要分析執行緒數,怎麼分析,分析什麼因素
為了達到執行緒數最優,系統執行最優,我們需要設定執行緒池中執行緒的數量。
如果是IO密集型,則將執行緒數設定為:((執行緒等待時間+執行緒CPU時間)/執行緒CPU時間)*CPU數目
如果是CPU密集型,則將執行緒數設定為:CPU核數+1
23.抽象方法和類方法的區別,static的抽象方法可以嗎?
抽象方法需要在子類中具體實現使用,最終還是通過物件來呼叫
類方法:通過類來呼叫,可以不通過物件呼叫
不可以建立static型別的抽象方法
24.說下Java的克隆體系
java的clone分為淺克隆和深克隆
淺克隆:只克隆基本型別的引數,對於物件型別的引數直接引用,而不是新建立一個物件
深克隆:相對於淺克隆而言,對於物件型別的成員變數,會建立一個新的物件,與原物件內容一致
未完待續...