歡迎光臨
每天分享高質量文章

一位資深Java的阿裡系公司實戰面試經驗,套路還是面試官的多

馬老師說過,員工的離職原因很多,只有兩點最真實:

1、錢,沒給到位

2、心,受委屈了

以下是佔小狼的一些實戰面試經驗分享,希望能幫助你們順利拿到理想Offer!

專案經驗

面試官在一開始會讓你進行自我介紹,主要是想讓你介紹一下自己做過的一些專案,看看你對這些專案的瞭解程度。

因為很多人簡歷上寫的專案並非都是從頭到尾都參與的,有些只是參與並實現了其中的一些模組而已,或是接手維護別人的專案,所以在你簡歷上所寫的和麵試過程中所說的專案經驗,你自己必須能夠瞭解來龍去脈。之後,面試官也會根據你的專案描述,對專案中的實現原理,或為什麼要這樣實現進行提問,如果你木訥住,不知如何作答,只會大大降低面試分。

面試場景:

面試官:(拿著簡歷)講講你最近做的這個專案

我: &……%¥#*&¥@%¥!,說了一大通

PS:不知道面試官聽進去多少,面試官會挑他熟知的知識點進行提問。

面試官:你說這個專案中用到了netty,能大概講講netty的執行緒模型麼?

我:(幸好我看過netty的原始碼)netty透過Reactor模型基於多路復用器接收並處理使用者請求(能講就多講一點),內部實現了兩個執行緒池,boss執行緒池和work執行緒池,其中boss執行緒池的執行緒負責處理請求的accept事件,當接收到accept事件的請求時,把對應的socket封裝到一個NioSocketChannel中,並交給work執行緒池,其中work執行緒池負責請求的read和write事件。

PS:透過口述加畫圖的方式,把請求的執行過程大概描述了一遍,時間有限,也不可能把所有的細節都說完,挑重點講,挑記憶深刻的講。

面試官:嗯,理解的還挺深入的…那你在做這個專案時有沒有遇到什麼困難,或者是覺得有挑戰的地方?

我:因為之前確實碰到了這個問題,當時做這個專案時,對netty的不過熟悉,把請求的業務邏輯放在work執行緒池的執行緒中進行處理,進行壓測的時候,發現qps總是上不去,後來看了原始碼之後才發現,由於業務邏輯的處理比較耗時,完全佔用了work執行緒池的資源,導致新的請求一直處於等待狀態。

PS:這時面試官想讓你自己出題自己回答了,所以一定要回答,不回答就突顯不出你這個專案了,要是這個問題沒有準備過,只能臨時發揮了,當然我就是屬於臨時發揮的

面試官:那最後是如何解決的?

我:最後把處理業務的邏輯封裝成一個task提交給一個新建的業務執行緒池中執行,執行完之後由work執行緒池執行請求的write事件。

面試官:好的,你知道nio中selector可能觸發bug麼?

我:嗯,對的,selector的select方法,因為底層的epoll函式可能會發生空轉,從而導致cpu100%。

面試官:那如何解決該問題?

我:這個問題在netty已經解決了,透過&^%&$^(把netty的解決方案說一遍)

面試官:嗯,對了,你們這個專案有給自己定指標麼?

我:有的……把自己專案的指標說了一通,如何進行AB實驗,如何迭代最佳化指標

面試官:嗯,好的 ,專案的問題先到這裡,我們來考察一下java的基本點吧。>

如上只是本人所做的一個專案,當然了,具體專案具體分析,也不是每個面試官問的點都一樣。如果面試官不懂netty,自然會挑別的問題進行提問,不過儘量嘗試著把問題往自己熟悉的方向去靠。

面試知識點

1、執行緒池

執行緒池的實現原理,這個知識點真的很重要,幾乎每次面試都會被問到,一般的提問方式有如下幾種:

  • 1、“講講執行緒池的實現原理”
  • 2、“執行緒池中的coreNum和maxNum有什麼不同”
  • 3、“在不同的業務場景中,執行緒池引數如何設定”

面試場景:

面試官:平時執行緒池用的多麼?

我:嗯,我的*專案中就用到了。

面試官:那好,你講講執行緒池的實現原理

我:能給我筆和紙麼,我畫圖分析給你看看,……假設初始化一個執行緒池,核心執行緒數是5,最大執行緒數是……

面試官:嗯,好的,你繼續…

我:在紙上畫了正方形,這個代表一個執行緒池,初始化的時候,裡面是沒有執行緒的

面試官:嗯,好的,你繼續…

我:又畫了一個細長的長方形,這個代表阻塞佇列,一開始裡面也是沒有任務的。當來了一個任務時,在正方形中畫了一個小圓圈,代表初始化了一個執行緒,如果再來一個任務,就再畫一個圓圈,表示再初始化了一個執行緒,連續畫了5個圓圈之後,如果第6個任務過來了…

面試官:嗯,好的,你繼續…

我:這時會把第6個任務放到阻塞佇列中..

面試官:嗯,然後呢?

我:現在執行緒池中不是有5個執行緒了麼,如果其中一個執行緒空閑了,就會從阻塞佇列中獲取第6個任務,進行執行..

面試官:嗯,對的,那如果任務產生的速度比消費的速度快呢?

我:如果執行緒池的5個執行緒都在running狀態,那麼任務就先儲存在阻塞佇列中

面試官:如果佇列滿了,怎麼辦?

我:如果佇列滿了,我們不是設定了最大執行緒數是10麼,而執行緒池中只有5個執行緒,這時會新建一個執行緒去執行不能儲存到阻塞佇列的任務,然後我又在正方形中畫了5個圓圈。

面試官:那如果執行緒池中的執行緒數達到10個了,阻塞佇列也滿了,怎麼辦?

我:這種情況透過自定義reject函式去處理這裡任務了,舒了一口去,以為問完了…

面試官:好的,那如果執行一段時間之後,阻塞佇列中的任務也執行完了,執行緒池中的執行緒會怎麼樣?

我:…這個好像超過核心執行緒數的執行緒會在空閑一段時間內自動回收…因為有點不記得這個邏輯了,回答的有點虛…

面試官:好的,那這種情況在什麼場景下會發生?

我:這個…那個…我好像沒有遇到過這樣的情況……

面試官:嗯,好的,你回去之後再好好想想。

我:……..

PS:面試真的會緊張,導致很多明明知道的東西卻全忘記了。所以一定要放鬆放鬆。而且有蠻多面試官其實會很耐心,會引導你,但也會沿著你的思路一直細問下去,所以一定要確保自己思維邏輯清晰。

我居然忘記了“秒殺”這個場景!

2、鎖的實現

在關於鎖的面試過程中,一般主要問Synchronized和ReentrantLock的實現原理,更有甚者會問讀寫鎖。

面試場景

面試官:都瞭解Java中的什麼鎖?

我:比如Synchronized和ReentrantLock…讀寫鎖用的不多,就沒研究了。

PS:我就怕被問讀寫鎖,因為一直沒去看。所以,對一些自己不瞭解的話題,儘量少說一點,也坦白承認自己不會。

面試官:那好,你先說說Synchronized的實現原理吧。

我:嗯,Synchronized是JVM實現的一種鎖,其中鎖的獲取和釋放分別是monitorenter和monitorexit指令,該鎖在實現上分為了偏向鎖、輕量級鎖和重量級鎖,其中偏向鎖在1.6是預設開啟的,輕量級鎖在多執行緒競爭的情況下會膨脹成重量級鎖,有關鎖的資料都儲存在物件頭中……

面試官:哦,嗯,理解的還挺透徹,那你說說ReentrantLock的實現吧…

我:ReentrantLock是基於AQS實現的

面試官:什麼是AQS?

我:在AQS內部會儲存一個狀態變數state,透過CAS修改該變數的值,修改成功的執行緒表示獲取到該鎖,沒有修改成功,或者發現狀態state已經是加鎖狀態,則透過一個Waiter物件封裝執行緒,新增到等待佇列中,並掛起等待被喚醒……

面試官:能說說CAS的實現原理麼?

我:CAS是透過unsafe類的compareAndSwap方法實現的(心裡得意的一笑)

面試官:哦,好的,那你知道這個方法的引數的含義的麼?

我:這個方法看的時間有點久遠了,第一個引數是要修改的物件,第二個引數是物件中要修改變數的偏移量,第三個引數是修改之前的值,第四個引數是預想修改後的值….

面試官:嗯,對的,那你知道作業系統級別是如何實現的麼?

我:(我去你大爺…)我只記得X86中有一個cmp開頭的指令,具體的我忘記了…

面試官:嗯,好,你知道CAS指令有什麼缺點麼

我:哦,CAS的缺點是存在ABA問題。

面試官:怎麼講?

我:就是一個變數V,如果變數V初次讀取的時候是A,並且在準備賦值的時候檢查到它仍然是A,那能說明它的值沒有被其他執行緒修改過了嗎?如果在這段期間它的值曾經被改成了B,然後又改回A,那CAS操作就會誤認為它從來沒有被修改過。

面試官:那怎麼解決?

我:(有完沒完了啊…我的心裡是崩潰的)針對這種情況,java併發包中提供了一個帶有標記的原子取用類”AtomicStampedReference”,它可以透過控制變數值的版本來保證CAS的正確性。

面試官:嗯,好的,這個問題到此為止,我們再看看別的。 我:….我能喝口水麼

3、ConcurrentHashMap

當考察資料結構時,面試官一開始會問HashMap的實現原理,當你說出HashMap並非執行緒安全之後,會讓你自己引出ConcurrentHashMap,接著就可能開始如下的對話。

面試場景

面試官:談談ConcurrentHashMap實現原理

我:……基於分段鎖的……,但是1.8之後改變實現方式了。

面試官:1.8啥方式?

我:……(把1.8的實現原理說了一通,其中提到了紅黑樹)…

面試官:能講下紅黑樹的概念嗎?

我:紅黑樹是一種二叉樹,並且是平衡……%……¥……,

面試官:能講下紅黑樹的……

我:打住,別問了,紅黑樹我只知道他是二叉樹,比其他樹多一個屬性,其他的我都不知道。 面試官:好的,那換個,你知道它的size方法是如何實現的麼?

我:size方法?是想要得到Map中的元素個數麼?

面試官:對的….

我:我記得好像size方法傳回是不準確的,平時也不會用到這個方法…

面試官:如果你覺得size方法傳回值不準確,那如果讓你自己實現,你覺得應該怎麼實現呢?

我:(兩眼一黑)等等,讓我想想…..應該可以用AtomicInteger變數進行記錄…嗯,對的,每次插入或刪除的時候,操作這個變數,我得意的一笑…

面試官:哦,是麼,那如果我覺得這個AtomicInteger這個變數效能不好,還能再最佳化麼?

我:懵逼臉…(當時居然把volitile變數給忘記了)…好像沒有了,我想不出來了…

面試官:哦,那回頭你再看看原始碼吧,jdk中已經實現了…

我:哦,是麼….

面試官:那今天的面試到此結束,我們後面會通知你。

我:……(結束專業用語)

贊(0)

分享創造快樂