作者:小傅哥
部落格:https://bugstack.cn
沉澱、分享、成長,讓自己和他人都能有所收穫!😄
一、前言
最近給大家整理一些面試現場,真實的面試題和答案以及總結
雖然技術的知識點是固定的,但不同大廠不同面試官的提問方式卻不一樣。一方面是你的簡歷的內容影響,另外一方面是受面試官的個人經歷導致。最終就看你們是否對脾氣了,如果不對換個部門重新投
但如果你能把一個知識點真的搞懂,是真的懂。那麼,無論面試官怎麼問,其實都能回答的很精彩,精彩決定了你的職位和薪資。
為了讓大家在以後的面試中都能精彩,像秀一樣,特此準備整理一些真實的面試現場分享給大家,希望對每一個求職時都有幫助。不過這些都是底層技術的學習幫助,如果你希望自己更牛,那麼要多學習、多積累!
如果本文涉及的 Java 核心內容不能很好的理解,可以閱讀小傅哥的《Java 面經手冊》,全書共5章29節,417頁11.5萬字,耗時4個月完成。涵蓋資料結構、演演算法邏輯、並行程式設計、JVM以及簡歷和網際網路大廠面試等內容。同時此書並不是單純的面試題,也不是內卷八股文。而是從一個單純的和程式設計師有關的數學知識點開始,深入講解 Java 的核心技術。
二、面試現場
背景
小夥伴面的是美團,求職方向是團隊技術負責人。此次面試以連環追問的方式為主,喜歡刨根問底,非常考研面試者的技術功底。以下是整理出的部分面試題
,我們看看這些題該如何回答。
先讓寫個執行緒安全的單例模式
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
public static Singleton getInstance(){
if(null != instance) return instance;
synchronized (Singleton.class){
if (null == instance){
instance = new Singleton();
}
}
return instance;
}
}
- 考察執行緒安全的單例模式,一方面是對基礎的瞭解,另一方面以單例模式作為入口考察並行程式設計的知識點。
- 在這裡你要知道,並行程式設計的三要素包括:原子性、可見性、有序性。
- 那具備三要素知識點的單例模式,主要是如上案例中的
雙重檢查鎖
和CAS忙等策略。而雙重檢查鎖的單例方式,對於面試官和求職者來說,可以往下繼續聊的點就有了。 - 當然,如果你沒有寫出這樣一種單例模式,大概率會被面試官引導過來。在面試的過程中最好的方式是主動和引導面試官走,也稱對脾氣,也就是技術臭味相投的感覺。
高並行下,單例模式會存在哪些問題?
- 單例模式就是以防止執行緒不安全和提高程式碼執行效率而設計的。
- 雙重鎖定檢查(DCL,Double Check Lock),也就是為此設計的。別被 DCL 唬住嘍
可見性和指令重排是怎麼回事?
- 可見性,Java 程式語言允許執行緒存取共用變數,為了確保共用變數能被準確和一致地更新,執行緒應該確保通過排它鎖單獨獲得這個變數。
- 指令重排,在程式執行過程中為了效能考慮,,編譯器和 CPU 可能會對指令重新排序。對於並行多執行緒場景下,指令重排會產生不確定的執行效果。
voliate 關鍵字為什麼可以解決可見性和指令重排?
可見性
- 首選,volatile 關鍵字修飾的共用變數可以提供這種可見性規範,也叫做讀寫可見。
- 被 volatile 關鍵字修飾的共用變數在轉換成組合語言時,會加上一個以 lock 為字首的指令,當CPU發現這個指令時,立即將當前核心快取記憶體行的資料回寫到記憶體,同時使在其他核心裡快取了該記憶體地址的資料無效。
- 另外,在早期的 CPU 中,是通過在匯流排加 LOCK# 鎖的方式實現的,但這種方式開銷較大。所以Intel開發了快取一致性協定,也就是 MESI 協定,該解決快取一致性。
volatile 的好處
,volatile 是一種非鎖機制,這種機制可以避免鎖機制引起的執行緒上下文切換和排程問題。所以,volatile 的執行成本比 synchronized 更低。volatile 的不足
,volatile 關鍵字只能保證可見性,不能保證原子性操作。- 此外如果你還能回答出,Unsafe.loadFence(); 保證在這個屏障之前的所有讀操作都已經完成。的一些使用,那麼面試絕對可以加分。
指令重排
public volatile boolean sign;
descriptor: Z
flags: ACC_PUBLIC, ACC_VOLATILE
- 從位元組碼層面,新增 ACC_VOLATILE,在組合指令的列印會有
lock addl $0x0,(%rsp)s
- 從 JVM 層面,JMM 提供了8個 Happen-Before 規則來約束資料之間競爭、4個記憶體屏障 (LL LS SL SS)和As-if-serial
- 從硬體層面,sfence、lfence、mfence
除了雙重檢查鎖之外,還有什麼別的辦法實現執行緒安全的單例模式。
public enum Singleton {
INSTANCE;
public void test(){
System.out.println("hi~");
}
}
@Test
public void test() {
Singleton_07.INSTANCE.test();
}
- 如果再讓寫一種差異比較大,方式不太一樣的單例模式,那麼 Effective Java 作者推薦使用列舉的方式這個時候可以甩出來秀一波了。
- 這種方式解決了最主要的;執行緒安全、自由序列化、單一範例。
你看過什麼原始碼嗎?JVM 的原始碼是否看過?
- 看過Dubbo、Spring、Mybatis等框架和一些中介軟體的原始碼,關於 JVM 多執行緒、並行、鎖等核心內容的原始碼有所瞭解。
- 其實這塊問你的內容,主要考察你對技術的學習是否有核心深度。如果你能對此有所回答,那麼會得到面試官的一定認可。
Dubbo是怎麼工作的?
- 簡單來說,引入 Dubbo 服務的介面提供方與介面消費方,通過註冊與拉取介面資訊,把服務雙方通過 Socket 進行連線。之後介面通訊的時候通過代理類傳輸 Socket 請求,再由介面提供方通過反射呼叫真實服務,最終把介面執行資訊返回給呼叫端。
- 在整個的回答過程中,可能會聊到註冊中心、代理、反射、通訊模型以及 Netty 的相關知識,這主要包括了通訊協定的定義、半包粘包以及流量整形和各類知識。
Dubbo通訊是用的什麼協定?
- Dubbo 主要支援這些協定:dubbo://、rmi://、hessian://、http://、webservice://、thrift://
- rmi 協定:走java二進位制序列化,多個短連線,適合消費者和提供者數量差不多,適用於檔案的傳輸,一般較少用
- dubbo協定: 預設就是走此協定,單一長連線,NIO 非同步通訊,基於 hessian 作為序列化協定
- hessian協定:走 hessian 序列化協定,多個短連線,適用於提供者數量比消費者數量還多,適用於檔案的傳輸,一般較少用
- http協定:走json序列化
- 此外序列化的方式還有protobuf,protobuf 全稱 Google Protocol Buffers,是 google 開發的一套用於資料儲存,網路通訊時用於協定編解碼的工具庫。
9 . 屬於網路傳輸中的哪一層?
- TCP/IP 四層模型,是 OSI 七層模型的簡化,泛指眾多(TCP,UDP,IP等)協定。
- Dubbo 協定是 TCP 協定之上的協定,採用單一長連線和 NIO 非同步通訊。
TCP/IP協定來說建立連線的時候,為什麼需要三次握手?
- 三次握手是在安全可靠的基礎上最少握手次數的方案,而兩次握手並不能保證可靠性,四次握手又浪費了傳輸效率。
- TCP 傳輸控制協定,是一個面向連線的協定。在TCP/IP協定中,TCP協定提供可靠的連線服務,連線是通過三次握手進行初始化的。對於這部分知識可以深入瞭解下,資料也很豐富。
你剛才說你們公司用的是Kafka,那麼你覺得什麼場景下要用到Kafka呢?
特性 | Kafka | RocketMQ | ActiveMQ | RabbitMQ |
---|
吞吐量 | 高吞吐量,可達 10w 級別 | 高吞吐量,可達 10w 級別 | 1w 級別,吞吐量相交比較低 | 1w 級別,吞吐量相交比較低 |
時效性 | 延遲在 ms 級 | 延遲在 ms 級 | 延遲在 ms 級 | 延遲在微妙級,延遲最低 |
可用性 | 天然的分散式系統,資料有副本機制,可用性非常高 | 分散式架構,可用性非常高 | 主從架構,可用性較高 | 同 ActiveMQ |
維護性 | 基於 Java 和 Scala 語言 實現,社群活躍度高,維護成本較低 | 基於 Java 語言實現,社群活躍度高,維護成本較低 | 基於 Java 語言實現,訊息佇列場景功能很完備,但社群活躍度較低,維護成本較高 | 基於 erlang 語言開發,社群活躍度一般,小團隊維護成本較高 |
- 首先要知道,開源社群有很多優秀的佇列中介軟體,比如 RabbitMQ、ActiveMQ、RocketMQ、Kafka,有些大廠還有自研的 MQ 佇列中介軟體。
- 解耦、消峰、驅動等場景下的業務時以及紀錄檔採集系統、監控系統、流式處理等各類場景中都離不開MQ佇列。
你覺得對於一個訊息中介軟體來說,需要達到哪些要求?
- 高吞吐、低延時、可用性和可維護性,是訊息佇列中介軟體的核心要求。
- 同時你可以說出,中介軟體的作用是解決共性凝練和複用,從本質上提升程式碼的複用性、鬆耦合和互操作的標準機制,從而提升研發整體交付效率。
Kafka是如何做到高吞吐量的?
- Kafka是分散式訊息系統,需要處理海量的訊息,Kafka的設計是把所有的訊息都寫入速度低容量大的硬碟,以此來換取更強的儲存能力,但實際上,使用硬碟並沒有帶來過多的效能損失。主要圍繞順序讀寫、零拷貝、檔案分段、批次傳送和資料壓縮幾個方面提高吞吐率。
接下來是關於一些專案的問題
- 在公司做過哪些專案,主要是哪方面?基礎中介軟體還是業務專案?這個專案的主要難點在哪裡?怎麼解決的?
- 專案做到現在,有沒有一些資料上的評價指標,表示這個專案做得不錯?如果沒有,那麼現在讓你自己評價一下,你覺得應該從哪些方面做考量?
- 對於一個系統來說,如何確保它的穩定性?(執行緒池用的哪種?為什麼要用這幾種?怎麼用的?)
- 你在專案當中扮演什麼樣的角色?系統Owner還是開發?
- 你們團隊的人員分佈是怎麼樣的?內編幾個,外包幾個?如果帶外包的話,如何管理外包?
面試覆盤
- 基礎知識要牢固,JVM記憶體分佈,多執行緒,基本是面試必問的。其中多執行緒並行的源頭:可見性,有序性,原子性相關的知識點一定要深入理解,能講多清楚就講多清楚,因為這些涉及到CPU,記憶體,指令集等底層知識,是多執行緒理論的源頭。這方面的東西,如果面試官本身具備一定實力的話,是很容易深究下去的,如果只是淺嘗輒止,一知半解,很容易暴露自己底層知識的不牢。逼格就會降低一個大的檔次。
- 要有一定動手能力,一些常見的設計模式要隨時隨地可以寫出來,如果有多種方案實現的話,需要都講出來,並指出其中的優缺點。
- 分散式理論要紮實,要深入理解常見RPC框架(如dubbo)和訊息佇列的設計和實現原理。一個框架的出現,以及平時業務開發所遇不到的各種高階知識點(比如dubbo的重試機制,熔斷,降級服務等,kafka相比ActiveMQ等其它訊息佇列,優勢在哪裡,為什麼它可以支撐那麼高的吞吐量等等),一定是為了解決某些特定問題才會出現的,瞭解了問題源頭,才能更好理解框架的全域性設計思想,然後才能更好地吸收框架裡面的各種解決方案以及背後體現出來的思想。
- 網路基礎要夯實,http,https,TCP/IP協定以及網路通訊的基礎知識還是要知道的。
- 實際專案一定要學會總結,讓人看到你做專案的亮點(程式碼規範,可維護性,可延伸性,穩定性,效能優化,存取量,以及一些其它的資料指標)。如果沒有,一定要想辦法自己加入一些可信的東西出來。畢竟面試官無法驗證你說的是真是假,如果說得很像那麼回事,面試官應該還是會認可的。
三、總結
- 如果你不希望面試時自己的薪資、待遇、職位,被別人安排來擺弄去,就要不斷的在開發過程中提煉、總結、歸納自己的知識項,找到個人的價值力量,不斷的去擴寬和加深。
- 我特別同意本文我的小夥伴
豆豆
的總結,也是此次求職者的分享;「程式設計師不是一個木偶人,不只是被動的接需求或者任務,也不能只是埋頭苦幹」。公司是沒有永遠穩定的,網際網路的變化也更多,只有自己擁有了留下的本事和走出去的能力,才是個人的最安全區域。 - 最後希望每一個研發小夥伴都能有所積累和沉澱,把那些視訊當電影、看文章當小說的毛病改改,要學會動起來,驗證起來,實踐才能讓一個知識更能落到自己的腦子裡。
四、系列推薦
一線網際網路軟體開發工程師,擅長編寫優秀的程式碼、中介軟體開發、架構設計等。| 公眾號:bugstack蟲洞棧,回覆:設計模式、面經手冊、位元組碼程式設計,可以下載我的PDF!