文章有點(diǎn)長(zhǎng),請(qǐng)耐心看完,絕對(duì)有收獲!不想聽(tīng)我BB直接進(jìn)入面試分享:
- 準(zhǔn)備過(guò)程
- 螞蟻金服面試分享
- 拼多多面試分享
- 字節(jié)跳動(dòng)面試分享
- 總結(jié)
說(shuō)起來(lái)開(kāi)始進(jìn)行面試是年前倒數(shù)第二周,上午9點(diǎn),我還在去公司的公交上,突然收到螞蟻的面試電話,其實(shí)算不上真正的面試。面試官只是和我聊了下他們?cè)谧龅氖虑椋ㄖ饕亲鲭p十一這里大促的穩(wěn)定性保障,偏中間件吧),說(shuō)的很詳細(xì),然后和我溝通了下是否有興趣,我表示有興趣,后面就收到正式面試的通知,最后沒(méi)選擇去螞蟻表示抱歉。
當(dāng)時(shí)我自己也準(zhǔn)備出去看看機(jī)會(huì),順便看看自己的實(shí)力。當(dāng)時(shí)我其實(shí)挺糾結(jié)的,一方面現(xiàn)在部門(mén)也正需要我,還是可以有一番作為的,另一方面覺(jué)得近一年來(lái)進(jìn)步緩慢,沒(méi)有以前飛速進(jìn)步的成就感了,而且業(yè)務(wù)和技術(shù)偏于穩(wěn)定,加上自己也屬于那種比較懶散的人,骨子里還是希望能夠突破現(xiàn)狀,持續(xù)在技術(shù)上有所精進(jìn)。
在開(kāi)始正式的總結(jié)之前,還是希望各位同仁能否聽(tīng)我繼續(xù)發(fā)泄一會(huì),抱拳!
我翻開(kāi)自己2018年初立的flag,覺(jué)得甚是慚愧。其中就有一條是保持一周寫(xiě)一篇博客,奈何中間因?yàn)楦鞣N原因沒(méi)能堅(jiān)持下去。細(xì)細(xì)想來(lái),主要是自己沒(méi)能真正靜下來(lái)心認(rèn)真投入到技術(shù)的研究和學(xué)習(xí),那么為什么會(huì)這樣?說(shuō)白了還是因?yàn)闆](méi)有確定目標(biāo)或者目標(biāo)不明確,沒(méi)有目標(biāo)或者目標(biāo)不明確都可能導(dǎo)致行動(dòng)的失敗。
那么問(wèn)題來(lái)了,目標(biāo)是啥?就我而言,短期目標(biāo)是深入研究某一項(xiàng)技術(shù),比如最近在研究mysql,那么深入研究一定要?jiǎng)邮謱?shí)踐并且有所產(chǎn)出,這就夠了么?還需要我們能夠舉一反三,結(jié)合實(shí)際開(kāi)發(fā)場(chǎng)景想一想日常開(kāi)發(fā)要注意什么,這中間有沒(méi)有什么坑?可以看出,要進(jìn)步真的不是一件簡(jiǎn)單的事,這種反人類的行為需要我們克服自我的弱點(diǎn),逐漸形成習(xí)慣。真正牛逼的人,從不覺(jué)得認(rèn)真學(xué)習(xí)是一件多么難的事,因?yàn)檫@已經(jīng)形成了他的習(xí)慣,就和早上起床刷牙洗臉那么自然簡(jiǎn)單。
扯了那么多,開(kāi)始進(jìn)入正題,先后進(jìn)行了螞蟻、拼多多和字節(jié)跳動(dòng)的面試。
準(zhǔn)備過(guò)程
先說(shuō)說(shuō)我自己的情況,我2016先在螞蟻實(shí)習(xí)了將近三個(gè)月,然后去了我現(xiàn)在的老東家,2.5年工作經(jīng)驗(yàn),可以說(shuō)畢業(yè)后就一直老老實(shí)實(shí)在老東家打怪升級(jí),雖說(shuō)有螞蟻的實(shí)習(xí)經(jīng)歷,但是因?yàn)闀r(shí)間太短,還是有點(diǎn)虛的。所以面試官看到我簡(jiǎn)歷第一個(gè)問(wèn)題絕對(duì)是這樣的。
“哇,你在螞蟻待過(guò),不錯(cuò)啊”,面試官笑嘻嘻地問(wèn)到?!笆堑模€好”,我說(shuō)?!盀樯恫湃齻€(gè)月?”,面試官臉色一沉問(wèn)到。“嘩啦啦解釋一通。。?!?,我解釋道?!芭?,原來(lái)如此,那我們開(kāi)始面試吧”,面試官一本正經(jīng)說(shuō)到。
尼瑪,早知道不寫(xiě)螞蟻的實(shí)習(xí)經(jīng)歷了,后面仔細(xì)一想,當(dāng)初寫(xiě)上螞蟻不就給簡(jiǎn)歷加點(diǎn)料嘛。
言歸正傳,準(zhǔn)備過(guò)程其實(shí)很早開(kāi)始了(當(dāng)然這不是說(shuō)我工作時(shí)老想著跳槽,因?yàn)槲颐靼赚F(xiàn)在的老東家并不是終點(diǎn),我還需要不斷提升),具體可追溯到從螞蟻離職的時(shí)候,當(dāng)時(shí)出來(lái)也面了很多公司,沒(méi)啥大公司,面了大概5家公司,都拿到offer了。
工作之余常常會(huì)去額外研究自己感興趣的技術(shù)以及工作用到的技術(shù),力求把原理搞明白,并且會(huì)自己實(shí)踐一把。此外,買了N多書(shū),基本有時(shí)間就會(huì)去看,補(bǔ)補(bǔ)基礎(chǔ),什么操作系統(tǒng)、數(shù)據(jù)結(jié)構(gòu)與算法、MySQL、JDK之類的源碼,基本都好好溫習(xí)了(文末會(huì)列一下自己看過(guò)的書(shū)和一些好的資料)。我深知基礎(chǔ)就像“木桶效應(yīng)”的短板,決定了能裝多少水。
此外,在正式?jīng)Q定看機(jī)會(huì)之前,我給自己列了一個(gè)提綱,主要包括Java要掌握的核心要點(diǎn),有不懂的就查資料搞懂。我給自己定位還是Java工程師,所以Java體系是一定要做到心中有數(shù)的,很多東西沒(méi)有常年的積累面試的時(shí)候很容易露餡,學(xué)習(xí)要對(duì)得起自己,不要騙人。
剩下的就是找平臺(tái)和內(nèi)推了,除了螞蟻,頭條和拼多多都是找人內(nèi)推的,感謝螞蟻面試官對(duì)我的欣賞,以后說(shuō)不定會(huì)去螞蟻咯。
平臺(tái):脈脈、GitHub、v2
螞蟻金服

一面
一面就做了一道算法題,要求兩小時(shí)內(nèi)完成,給了長(zhǎng)度為N的有重復(fù)元素的數(shù)組,要求輸出第10大的數(shù)。典型的TopK問(wèn)題,快排算法搞定。
算法題要注意的是合法性校驗(yàn)、邊界條件以及異常的處理。另外,如果要寫(xiě)測(cè)試用例,一定要保證測(cè)試覆蓋場(chǎng)景盡可能全。加上平時(shí)刷刷算法題,這種考核應(yīng)該沒(méi)問(wèn)題的。
二面
- 自我介紹下唄
- 開(kāi)源項(xiàng)目貢獻(xiàn)過(guò)代碼么?(Dubbo提過(guò)一個(gè)打印accesslog的bug算么)
- 目前在部門(mén)做什么,業(yè)務(wù)簡(jiǎn)單介紹下,內(nèi)部有哪些系統(tǒng),作用和交互過(guò)程說(shuō)下
- Dubbo踩過(guò)哪些坑,分別是怎么解決的?(說(shuō)了異常處理時(shí)業(yè)務(wù)異常捕獲的問(wèn)題,自定義了一個(gè)異常攔截器)
- 開(kāi)始進(jìn)入正題,說(shuō)下你對(duì)線程安全的理解(多線程訪問(wèn)同一個(gè)對(duì)象,如果不需要考慮額外的同步,調(diào)用對(duì)象的行為就可以獲得正確的結(jié)果就是線程安全)
- 事務(wù)有哪些特性?(ACID)
- 怎么理解原子性?(同一個(gè)事務(wù)下,多個(gè)操作要么成功要么失敗,不存在部分成功或者部分失敗的情況)
- 樂(lè)觀鎖和悲觀鎖的區(qū)別?(悲觀鎖假定會(huì)發(fā)生沖突,訪問(wèn)的時(shí)候都要先獲得鎖,保證同一個(gè)時(shí)刻只有線程獲得鎖,讀讀也會(huì)阻塞;樂(lè)觀鎖假設(shè)不會(huì)發(fā)生沖突,只有在提交操作的時(shí)候檢查是否有沖突)這兩種鎖在Java和MySQL分別是怎么實(shí)現(xiàn)的?(Java樂(lè)觀鎖通過(guò)CAS實(shí)現(xiàn),悲觀鎖通過(guò)synchronize實(shí)現(xiàn)。mysql樂(lè)觀鎖通過(guò)MVCC,也就是版本實(shí)現(xiàn),悲觀鎖可以通過(guò)select... for update加上排它鎖)
- HashMap為什么不是線程安全的?(多線程操作無(wú)并發(fā)控制,順便說(shuō)了在擴(kuò)容的時(shí)候多線程訪問(wèn)時(shí)會(huì)造成死鎖,會(huì)形成一個(gè)環(huán),不過(guò)擴(kuò)容時(shí)多線程操作形成環(huán)的問(wèn)題再JDK1.8已經(jīng)解決,但多線程下使用HashMap還會(huì)有一些其他問(wèn)題比如數(shù)據(jù)丟失,所以多線程下不應(yīng)該使用HashMap,而應(yīng)該使用ConcurrentHashMap)怎么讓HashMap變得線程安全?(Collections的synchronize方法包裝一個(gè)線程安全的Map,或者直接用ConcurrentHashMap)兩者的區(qū)別是什么?(前者直接在put和get方法加了synchronize同步,后者采用了分段鎖以及CAS支持更高的并發(fā))
- jdk1.8對(duì)ConcurrentHashMap做了哪些優(yōu)化?(插入的時(shí)候如果數(shù)組元素使用了紅黑樹(shù),取消了分段鎖設(shè)計(jì),synchronize替代了Lock鎖)為什么這樣優(yōu)化?(避免沖突嚴(yán)重時(shí)鏈表多長(zhǎng),提高查詢效率,時(shí)間復(fù)雜度從O(N)提高到O(logN))
- redis主從機(jī)制了解么?怎么實(shí)現(xiàn)的?
- 有過(guò)GC調(diào)優(yōu)的經(jīng)歷么?(有點(diǎn)虛,答得不是很好)
- 有什么想問(wèn)的么?
三面
- 簡(jiǎn)單自我介紹下
- 監(jiān)控系統(tǒng)怎么做的,分為哪些模塊,模塊之間怎么交互的?用的什么數(shù)據(jù)庫(kù)?(MySQL)使用什么存儲(chǔ)引擎,為什么使用InnnoDB?(支持事務(wù)、聚簇索引、MVCC)
- 訂單表有做拆分么,怎么拆的?(垂直拆分和水平拆分)
- 水平拆分后查詢過(guò)程描述下
- 如果落到某個(gè)分片的數(shù)據(jù)很大怎么辦?(按照某種規(guī)則,比如哈希取模、range,將單張表拆分為多張表)
- 哈希取模會(huì)有什么問(wèn)題么?(有的,數(shù)據(jù)分布不均,擴(kuò)容縮容相對(duì)復(fù)雜 )
- 分庫(kù)分表后怎么解決讀寫(xiě)壓力?(一主多從、多主多從)
- 拆分后主鍵怎么保證惟一?(UUID、Snowflake算法)
- Snowflake生成的ID是全局遞增唯一么?(不是,只是全局唯一,單機(jī)遞增)
- 怎么實(shí)現(xiàn)全局遞增的唯一ID?(講了TDDL的一次取一批ID,然后再本地慢慢分配的做法)
- Mysql的索引結(jié)構(gòu)說(shuō)下(說(shuō)了B+樹(shù),B+樹(shù)可以對(duì)葉子結(jié)點(diǎn)順序查找,因?yàn)槿~子結(jié)點(diǎn)存放了數(shù)據(jù)結(jié)點(diǎn)且有序)
- 主鍵索引和普通索引的區(qū)別(主鍵索引的葉子結(jié)點(diǎn)存放了整行記錄,普通索引的葉子結(jié)點(diǎn)存放了主鍵ID,查詢的時(shí)候需要做一次回表查詢)一定要回表查詢么?(不一定,當(dāng)查詢的字段剛好是索引的字段或者索引的一部分,就可以不用回表,這也是索引覆蓋的原理)
- 你們系統(tǒng)目前的瓶頸在哪里?
- 你打算怎么優(yōu)化?簡(jiǎn)要說(shuō)下你的優(yōu)化思路
- 有什么想問(wèn)我么?
四面
- 介紹下自己
- 為什么要做逆向?
- 怎么理解微服務(wù)?
- 服務(wù)治理怎么實(shí)現(xiàn)的?(說(shuō)了限流、壓測(cè)、監(jiān)控等模塊的實(shí)現(xiàn))
- 這個(gè)不是中間件做的事么,為什么你們部門(mén)做?(當(dāng)時(shí)沒(méi)有單獨(dú)的中間件團(tuán)隊(duì),微服務(wù)剛搞不久,需要進(jìn)行監(jiān)控和性能優(yōu)化)
- 說(shuō)說(shuō)Spring的生命周期吧
- 說(shuō)說(shuō)GC的過(guò)程(說(shuō)了young gc和full gc的觸發(fā)條件和回收過(guò)程以及對(duì)象創(chuàng)建的過(guò)程)
- CMS GC有什么問(wèn)題?(并發(fā)清除算法,浮動(dòng)垃圾,短暫停頓)
- 怎么避免產(chǎn)生浮動(dòng)垃圾?(記得有個(gè)VM參數(shù)設(shè)置可以讓掃描新生代之前進(jìn)行一次young gc,但是因?yàn)間c是虛擬機(jī)自動(dòng)調(diào)度的,所以不保證一定執(zhí)行。但是還有參數(shù)可以讓虛擬機(jī)強(qiáng)制執(zhí)行一次young gc)
- 強(qiáng)制young gc會(huì)有什么問(wèn)題?(STW停頓時(shí)間變長(zhǎng))
- 知道G1么?(了解一點(diǎn) )
- 回收過(guò)程是怎么樣的?(young gc、并發(fā)階段、混合階段、full gc,說(shuō)了Remember Set)
- 你提到的Remember Set底層是怎么實(shí)現(xiàn)的?
- 有什么想問(wèn)的么?
五面
五面是HRBP面的,和我提前預(yù)約了時(shí)間,主要聊了之前在螞蟻的實(shí)習(xí)經(jīng)歷、部門(mén)在做的事情、職業(yè)發(fā)展、福利待遇等。阿里面試官確實(shí)是具有一票否決權(quán)的,很看重你的價(jià)值觀是否match,一般都比較喜歡皮實(shí)的候選人。HR面一定要誠(chéng)實(shí),不要說(shuō)謊,只要你說(shuō)謊HR都會(huì)去證實(shí),直接cut了。
- 之前螞蟻實(shí)習(xí)三個(gè)月怎么不留下來(lái)?
- 實(shí)習(xí)的時(shí)候主管是誰(shuí)?
- 實(shí)習(xí)做了哪些事情?(尼瑪這種也問(wèn)?)
- 你對(duì)技術(shù)怎么看?平時(shí)使用什么技術(shù)棧?(阿里HR真的是既當(dāng)?shù)之?dāng)媽,)
- 最近有在研究什么東西么
- 你對(duì)SRE怎么看
- 對(duì)待遇有什么預(yù)期么
最后HR還對(duì)我說(shuō)目前穩(wěn)定性保障部挺缺人的,希望我盡快回復(fù)。
小結(jié)
螞蟻面試比較重視基礎(chǔ),所以Java那些基本功一定要扎實(shí)。螞蟻的工作環(huán)境還是挺贊的,因?yàn)槲颐娴氖欠€(wěn)定性保障部門(mén),還有許多單獨(dú)的小組,什么三年1班,很有青春的感覺(jué)。面試官基本水平都比較高,基本都P7以上,除了基礎(chǔ)還問(wèn)了不少架構(gòu)設(shè)計(jì)方面的問(wèn)題,收獲還是挺大的。
拼多多

面試前
面完螞蟻后,早就聽(tīng)聞拼多多這個(gè)獨(dú)角獸,決定也去面一把。首先我在脈脈找了一個(gè)拼多多的HR,加了微信聊了下,發(fā)了簡(jiǎn)歷便開(kāi)始我的拼多多面試之旅。這里要非常感謝拼多多HR小姐姐,從面試內(nèi)推到offer確認(rèn)一直都在幫我,人真的很nice。
一面
- 為啥螞蟻只待了三個(gè)月?沒(méi)轉(zhuǎn)正?(轉(zhuǎn)正了,解釋了一通。。。)
- Java中的HashMap、TreeMap解釋下?(TreeMap紅黑樹(shù),有序,HashMap無(wú)序,數(shù)組+鏈表)
- TreeMap查詢寫(xiě)入的時(shí)間復(fù)雜度多少?(O(logN))
- HashMap多線程有什么問(wèn)題?(線程安全,死鎖)怎么解決?( jdk1.8用了synchronize + CAS,擴(kuò)容的時(shí)候通過(guò)CAS檢查是否有修改,是則重試)重試會(huì)有什么問(wèn)題么?(CAS(Compare And Swap)是比較和交換,不會(huì)導(dǎo)致線程阻塞,但是因?yàn)橹卦囀峭ㄟ^(guò)自旋實(shí)現(xiàn)的,所以仍然會(huì)占用CPU時(shí)間,還有ABA的問(wèn)題)怎么解決?(超時(shí),限定自旋的次數(shù),ABA可以通過(guò)原理變量AtomicStampedReference解決,原理利用版本號(hào)進(jìn)行比較)超過(guò)重試次數(shù)如果仍然失敗怎么辦?(synchronize互斥鎖)
- CAS和synchronize有什么區(qū)別?都用synchronize不行么?(CAS是樂(lè)觀鎖,不需要阻塞,硬件級(jí)別實(shí)現(xiàn)的原子性;synchronize會(huì)阻塞,JVM級(jí)別實(shí)現(xiàn)的原子性。使用場(chǎng)景不同,線程沖突嚴(yán)重時(shí)CAS會(huì)造成CPU壓力過(guò)大,導(dǎo)致吞吐量下降,synchronize的原理是先自旋然后阻塞,線程沖突嚴(yán)重仍然有較高的吞吐量,因?yàn)榫€程都被阻塞了,不會(huì)占用CPU )
- 如果要保證線程安全怎么辦?(ConcurrentHashMap)
- ConcurrentHashMap怎么實(shí)現(xiàn)線程安全的?(分段鎖)
- get需要加鎖么,為什么?(不用,volatile關(guān)鍵字)
- volatile的作用是什么?(保證內(nèi)存可見(jiàn)性)
- 底層怎么實(shí)現(xiàn)的?(說(shuō)了主內(nèi)存和工作內(nèi)存,讀寫(xiě)內(nèi)存屏障,happen-before,并在紙上畫(huà)了線程交互圖)
- 在多核CPU下,可見(jiàn)性怎么保證?(思考了一會(huì),總線嗅探技術(shù))
- 聊項(xiàng)目,系統(tǒng)之間是怎么交互的?
- 系統(tǒng)并發(fā)多少,怎么優(yōu)化?
- 給我一張紙,畫(huà)了一個(gè)九方格,都填了數(shù)字,給一個(gè)MN矩陣,從1開(kāi)始逆時(shí)針打印這MN個(gè)數(shù),要求時(shí)間復(fù)雜度盡可能低(內(nèi)心OS:之前貌似碰到過(guò)這題,最優(yōu)解是怎么實(shí)現(xiàn)來(lái)著)思考中。。。
- 可以先說(shuō)下你的思路(想起來(lái)了,說(shuō)了什么時(shí)候要變換方向的條件,向右、向下、向左、向上,依此循環(huán))
- 有什么想問(wèn)我的?
二面
- 自我介紹下
- 手上還有其他offer么?(拿了螞蟻的offer)
- 部門(mén)組織結(jié)構(gòu)是怎樣的?(這輪不是技術(shù)面么,不過(guò)還是老老實(shí)實(shí)說(shuō)了)
- 系統(tǒng)有哪些模塊,每個(gè)模塊用了哪些技術(shù),數(shù)據(jù)怎么流轉(zhuǎn)的?(面試官有點(diǎn)禿頂,一看級(jí)別就很高)給了我一張紙,我在上面簡(jiǎn)單畫(huà)了下系統(tǒng)之間的流轉(zhuǎn)情況
- 鏈路追蹤的信息是怎么傳遞的?(RpcContext的attachment,說(shuō)了Span的結(jié)構(gòu):parentSpanId + curSpanId)
- SpanId怎么保證唯一性?(UUID,說(shuō)了下內(nèi)部的定制改動(dòng))
- RpcContext是在什么維度傳遞的?(線程)
- Dubbo的遠(yuǎn)程調(diào)用怎么實(shí)現(xiàn)的?(講了讀取配置、拼裝url、創(chuàng)建Invoker、服務(wù)導(dǎo)出、服務(wù)注冊(cè)以及消費(fèi)者通過(guò)動(dòng)態(tài)代理、filter、獲取Invoker列表、負(fù)載均衡等過(guò)程(嘩啦啦講了10多分鐘),我可以喝口水么)
- Spring的單例是怎么實(shí)現(xiàn)的?(單例注冊(cè)表)
- 為什么要單獨(dú)實(shí)現(xiàn)一個(gè)服務(wù)治理框架?(說(shuō)了下內(nèi)部剛搞微服務(wù)不久,主要對(duì)服務(wù)進(jìn)行一些監(jiān)控和性能優(yōu)化)
- 誰(shuí)主導(dǎo)的??jī)?nèi)部還在使用么?
- 逆向有想過(guò)怎么做成通用么?
- 有什么想問(wèn)的么?
三面
二面老大面完后就直接HR面了,主要問(wèn)了些職業(yè)發(fā)展、是否有其他offer、以及入職意向等問(wèn)題,順便說(shuō)了下公司的福利待遇等,都比較常規(guī)啦。不過(guò)要說(shuō)的是手上有其他offer或者大廠經(jīng)歷會(huì)有一定加分。
小結(jié)
拼多多的面試流程就簡(jiǎn)單許多,畢竟是一個(gè)成立三年多的公司。面試難度中規(guī)中矩,只要基礎(chǔ)扎實(shí)應(yīng)該不是問(wèn)題。但不得不說(shuō)工作強(qiáng)度很大,開(kāi)始面試前HR就提前和我確認(rèn)能否接受這樣強(qiáng)度的工作,想來(lái)的老鐵還是要做好準(zhǔn)備
字節(jié)跳動(dòng)

面試前
頭條的面試是三家里最專業(yè)的,每次面試前有專門(mén)的HR和你約時(shí)間,確定OK后再進(jìn)行面試。每次都是通過(guò)視頻面試,因?yàn)槎际侵岸际请娫捗婊颥F(xiàn)場(chǎng)面,所以視頻面試還是有點(diǎn)不自然。也有人覺(jué)得視頻面試體驗(yàn)很贊,當(dāng)然蘿卜青菜各有所愛(ài)。最坑的二面的時(shí)候?qū)Ψ矫嬖嚬俚木W(wǎng)絡(luò)老是掉線,最后很冤枉的掛了(當(dāng)然有一些點(diǎn)答得不好也是原因之一)。所以還是有點(diǎn)遺憾的。
一面
- 先自我介紹下
- 聊項(xiàng)目,逆向系統(tǒng)是什么意思
- 聊項(xiàng)目,逆向系統(tǒng)用了哪些技術(shù)
- 線程池的線程數(shù)怎么確定?
- 如果是IO操作為主怎么確定?
- 如果計(jì)算型操作又怎么確定?
- Redis熟悉么,了解哪些數(shù)據(jù)結(jié)構(gòu)?(說(shuō)了zset) zset底層怎么實(shí)現(xiàn)的?(跳表)
- 跳表的查詢過(guò)程是怎么樣的,查詢和插入的時(shí)間復(fù)雜度?(說(shuō)了先從第一層查找,不滿足就下沉到第二層找,因?yàn)槊恳粚佣际怯行虻?,?xiě)入和插入的時(shí)間復(fù)雜度都是O(logN))
- 紅黑樹(shù)了解么,時(shí)間復(fù)雜度?(說(shuō)了是N叉平衡樹(shù),O(logN))
- 既然兩個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí)間復(fù)雜度都是O(logN),zset為什么不用紅黑樹(shù)(跳表實(shí)現(xiàn)簡(jiǎn)單,踩坑成本低,紅黑樹(shù)每次插入都要通過(guò)旋轉(zhuǎn)以維持平衡,實(shí)現(xiàn)復(fù)雜)
- 點(diǎn)了點(diǎn)頭,說(shuō)下Dubbo的原理?(說(shuō)了服務(wù)注冊(cè)與發(fā)布以及消費(fèi)者調(diào)用的過(guò)程)踩過(guò)什么坑沒(méi)有?(說(shuō)了dubbo異常處理的和打印accesslog的問(wèn)題)
- CAS了解么?(說(shuō)了CAS的實(shí)現(xiàn))還了解其他同步機(jī)制么?(說(shuō)了synchronize以及兩者的區(qū)別,一個(gè)樂(lè)觀鎖,一個(gè)悲觀鎖)
- 那我們做一道題吧,數(shù)組A,2*n個(gè)元素,n個(gè)奇數(shù)、n個(gè)偶數(shù),設(shè)計(jì)一個(gè)算法,使得數(shù)組奇數(shù)下標(biāo)位置放置的都是奇數(shù),偶數(shù)下標(biāo)位置放置的都是偶數(shù)
- 先說(shuō)下你的思路(從0下標(biāo)開(kāi)始遍歷,如果是奇數(shù)下標(biāo)判斷該元素是否奇數(shù),是則跳過(guò),否則從該位置尋找下一個(gè)奇數(shù))
- 下一個(gè)奇數(shù)?怎么找?(有點(diǎn)懵逼,思考中。。)
- 有思路么?(仍然是先遍歷一次數(shù)組,并對(duì)下標(biāo)進(jìn)行判斷,如果下標(biāo)屬性和該位置元素不匹配從當(dāng)前下標(biāo)的下一個(gè)遍歷數(shù)組元素,然后替換)
- 你這樣時(shí)間復(fù)雜度有點(diǎn)高,如果要求O(N)要怎么做(思考一會(huì),答道“定義兩個(gè)指針,分別從下標(biāo)0和1開(kāi)始遍歷,遇見(jiàn)奇數(shù)位是是偶數(shù)和偶數(shù)位是奇數(shù)就停下,交換內(nèi)容”)
- 時(shí)間差不多了,先到這吧。你有什么想問(wèn)我的?
二面
- 面試官和藹很多,你先介紹下自己吧
- 你對(duì)服務(wù)治理怎么理解的?
- 項(xiàng)目中的限流怎么實(shí)現(xiàn)的?(Guava ratelimiter,令牌桶算法)
- 具體怎么實(shí)現(xiàn)的?(要點(diǎn)是固定速率且令牌數(shù)有限)
- 如果突然很多線程同時(shí)請(qǐng)求令牌,有什么問(wèn)題?(導(dǎo)致很多請(qǐng)求積壓,線程阻塞)
- 怎么解決呢?(可以把積壓的請(qǐng)求放到消息隊(duì)列,然后異步處理)
- 如果不用消息隊(duì)列怎么解決?(說(shuō)了RateLimiter預(yù)消費(fèi)的策略)
- 分布式追蹤的上下文是怎么存儲(chǔ)和傳遞的?(ThreadLocal + spanId,當(dāng)前節(jié)點(diǎn)的spanId作為下個(gè)節(jié)點(diǎn)的父spanId)
- Dubbo的RpcContext是怎么傳遞的?(ThreadLocal)主線程的ThreadLocal怎么傳遞到線程池?(說(shuō)了先在主線程通過(guò)ThreadLocal的get方法拿到上下文信息,在線程池創(chuàng)建新的ThreadLocal并把之前獲取的上下文信息設(shè)置到ThreadLocal中。這里要注意的線程池創(chuàng)建的ThreadLocal要在finally中手動(dòng)remove,不然會(huì)有內(nèi)存泄漏的問(wèn)題)
- 你說(shuō)的內(nèi)存泄漏具體是怎么產(chǎn)生的?(說(shuō)了ThreadLocal的結(jié)構(gòu),主要分兩種場(chǎng)景:主線程仍然對(duì)ThreadLocal有引用和主線程不存在對(duì)ThreadLocal的引用。第一種場(chǎng)景因?yàn)橹骶€程仍然在運(yùn)行,所以還是有對(duì)ThreadLocal的引用,那么ThreadLocal變量的引用和value是不會(huì)被回收的。第二種場(chǎng)景雖然主線程不存在對(duì)ThreadLocal的引用,且該引用是弱引用,所以會(huì)在gc的時(shí)候被回收,但是對(duì)用的value不是弱引用,不會(huì)被內(nèi)存回收,仍然會(huì)造成內(nèi)存泄漏)
- 線程池的線程是不是必須手動(dòng)remove才可以回收value?(是的,因?yàn)榫€程池的核心線程是一直存在的,如果不清理,那么核心線程的threadLocals變量會(huì)一直持有ThreadLocal變量)
- 那你說(shuō)的內(nèi)存泄漏是指主線程還是線程池?(主線程 )
- 可是主線程不是都退出了,引用的對(duì)象不應(yīng)該會(huì)主動(dòng)回收么?(面試官和內(nèi)存泄漏杠上了),沉默了一會(huì)。。。
- 那你說(shuō)下SpringMVC不同用戶登錄的信息怎么保證線程安全的?(剛才解釋的有點(diǎn)懵逼,一下沒(méi)反應(yīng)過(guò)來(lái),居然回答成鎖了。大腦有點(diǎn)暈了,此時(shí)已經(jīng)一個(gè)小時(shí)過(guò)去了,感覺(jué)情況不妙。。。)
- 這個(gè)直接用ThreadLocal不就可以么,你見(jiàn)過(guò)SpringMVC有鎖實(shí)現(xiàn)的代碼么?(有點(diǎn)暈菜。。。)
- 我們聊聊mysql吧,說(shuō)下索引結(jié)構(gòu)(說(shuō)了B+樹(shù))
- 為什么使用B+樹(shù)?( 說(shuō)了查詢效率高,O(logN),可以充分利用磁盤(pán)預(yù)讀的特性,多叉樹(shù),深度小,葉子結(jié)點(diǎn)有序且存儲(chǔ)數(shù)據(jù))
- 什么是索引覆蓋?(忘記了。。。)
- Java為什么要設(shè)計(jì)雙親委派模型?
- 什么時(shí)候需要自定義類加載器?
- 我們做一道題吧,手寫(xiě)一個(gè)對(duì)象池
- 有什么想問(wèn)我的么?(感覺(jué)我很多點(diǎn)都沒(méi)答好,是不是掛了(結(jié)果真的是) )
小結(jié)
頭條的面試確實(shí)很專業(yè),每次面試官會(huì)提前給你發(fā)一個(gè)視頻鏈接,然后準(zhǔn)點(diǎn)開(kāi)始面試,而且考察的點(diǎn)都比較全。
面試官都有一個(gè)特點(diǎn),會(huì)抓住一個(gè)值得深入的點(diǎn)或者你沒(méi)說(shuō)清楚的點(diǎn)深入下去直到你把這個(gè)點(diǎn)講清楚,不然面試官會(huì)覺(jué)得你并沒(méi)有真正理解。二面面試官給了我一點(diǎn)建議,研究技術(shù)的時(shí)候一定要去研究產(chǎn)生的背景,弄明白在什么場(chǎng)景解決什么特定的問(wèn)題,其實(shí)很多技術(shù)內(nèi)部都是相通的。很誠(chéng)懇,還是很感謝這位面試官大大。
總結(jié)
從年前開(kāi)始面試到頭條面完大概一個(gè)多月的時(shí)間,真的有點(diǎn)身心俱疲的感覺(jué)。最后拿到了拼多多、螞蟻的offer,還是蠻幸運(yùn)的。頭條的面試對(duì)我?guī)椭艽?,再次感謝面試官對(duì)我的誠(chéng)懇建議,以及拼多多的HR對(duì)我的啰嗦的問(wèn)題詳細(xì)解答。
這里要說(shuō)的是面試前要做好兩件事:簡(jiǎn)歷和自我介紹,簡(jiǎn)歷要好好回顧下自己做的一些項(xiàng)目,然后挑幾個(gè)亮點(diǎn)項(xiàng)目。自我介紹基本每輪面試都有,所以最好提前自己練習(xí)下,想好要講哪些東西,分別怎么講。此外,簡(jiǎn)歷提到的技術(shù)一定是自己深入研究過(guò)的,沒(méi)有深入研究也最好找點(diǎn)資料預(yù)熱下,不打無(wú)準(zhǔn)備的仗。
這些年看過(guò)的書(shū):
《Effective Java》、《現(xiàn)代操作系統(tǒng)》、《TCP/IP詳解:卷一》、《代碼整潔之道》、《重構(gòu)》、《Java程序性能優(yōu)化》、《Spring實(shí)戰(zhàn)》、《Zookeeper》、《高性能MySQL》、《億級(jí)網(wǎng)站架構(gòu)核心技術(shù)》、《可伸縮服務(wù)架構(gòu)》、《Java編程思想》
說(shuō)實(shí)話這些書(shū)很多只看了一部分,我通常會(huì)帶著問(wèn)題看書(shū),不然看著看著就睡著了,簡(jiǎn)直是催眠良藥。
****最后,附一張面試前準(zhǔn)備資料**
