
作者:小傅哥
部落格: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 的執行成本比 synchronized 更低。volatile 的好處
-
,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 級别 | 1w 級别,吞吐量相交比較低 | ||
時效性 | 延遲在 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協定以及網絡通信的基礎知識還是要知道的。
- 實際項目一定要學會總結,讓人看到你做項目的亮點(代碼規範,可維護性,可擴充性,穩定性,性能優化,通路量,以及一些其它的資料名額)。如果沒有,一定要想辦法自己加入一些可信的東西出來。畢竟面試官無法驗證你說的是真是假,如果說得很像那麼回事,面試官應該還是會認可的。
三、總結
- 如果你不希望面試時自己的薪資、待遇、職位,被别人安排來擺弄去,就要不斷的在開發過程中提煉、總結、歸納自己的知識項,找到個人的價值力量,不斷的去擴寬和加深。
- 我特别同意本文我的小夥伴
的總結,也是此次求職者的分享;“程式員不是一個木偶人,不隻是被動的接需求或者任務,也不能隻是埋頭苦幹”。公司是沒有永遠穩定的,網際網路的變化也更多,隻有自己擁有了留下的本事和走出去的能力,才是個人的最安全區域。豆豆
- 最後希望每一個研發小夥伴都能有所積累和沉澱,把那些視訊當電影、看文章當小說的毛病改改,要學會動起來,驗證起來,實踐才能讓一個知識更能落到自己的腦子裡。
四、系列推薦
- 不會寫履歷看這個:《半年招聘篩選了400+份履歷,告訴你怎麼寫容易被撩!》
- 問的答不上看這個:《Java 面經手冊》PDF,全書 417 頁 11.5 萬字
- 想刺激自己看這個:《數學,離一個程式員有多近?》
- 可以入職了看這個:《一次代碼評審,差點過不了試用期!》
公衆号:bugstack蟲洞棧 | 作者小傅哥多年從事一線網際網路 Java 開發的學習曆程技術彙總,旨在為大家提供一個清晰詳細的學習教程,側重點更傾向編寫Java核心内容。如果能為您提供幫助,請給予支援(關注、點贊、分享)!