阿里面試官用HashMap把我問倒了


本人是一名大三學生,最近在找暑期實習,其中也面試過兩次阿里,一次菜鳥網絡部門、一次網商銀行部門,當然我都失敗了,同時也讓我印象很深刻,因此記錄了其中一些面試心得,我覺得這個問題很值得分享,因此分享給大家

你能說一下HashMap的實現原理嗎?

對於這個問題,我當時覺得這個問題太小菜一碟了,於是照着自己之前准備的開始巴拉巴拉介紹HashMap,當我說到哈希沖突時,面試官打斷了我,問我,你知道HashMap如何解決哈希沖突的嗎?這個我想都沒想直接說鏈地址法,於是面試官又繼續問,那你還知道有哪些解決Hash沖突的方法,我當時整好記得一個開放尋址法,於是面試官又繼續問

你能說一下開放尋址法的原理嗎?

到這里我已經有點懵了,我就照着字面意思解釋了一番,標准解答如下:當哈希碰撞發生時,從發生碰撞的那個單元起,按照一定的次序,從哈希表中尋找一個空閑的單元,然后把發生沖突的元素存入到該單元。

於是面試官又問,如果用開放尋址法實現HashMap,能刪除節點嗎?此時我已語塞,因為我知道不管是回答能還是不能,他下一句肯定是為什么能或者為什么不能

面試關看我這里不會,於是換了個方向,接着問

你知道開放尋址法有哪些地方用到,或者說有哪些應用?

整好,我學過ThreadLocal,並當時了解過ThreadLocal的底層是使用ThreadLocalMap實現的,而ThreadLocalMap 的底層解決哈希沖突的方式正是開放尋址法,於是我將這些說了出來,於是面試官接着問

說說你對ThreadLocal的理解

於是我照着自己的理解介紹了一下ThreadLocal,面試官接着問,ThreadLocal有哪些應用,我答在與數據庫進行交互的時候,需要保證數據庫連接的一致性,此時就用到了ThreadLocal保證同一個事物中對數據庫的操作是用的同一個數據庫連接(其實當時我只想的到這個了),於是面試官接着問

ThreadLocal存在哪些問題

學過ThreadLocal 的人應該都知道,ThreadLocal其實是存在內存泄漏的問題,一個是key的內存泄漏,一個是value的內存泄漏,面試官接着問,那你說說ThreadLocal是如何解決這些問題的,我答:

  • 對於key 的內存泄漏:ThreadLocalMap 的key實際上是一個弱引用,當ThreaLocal對象為null時,這個key就會被回收,就不會造成內存泄漏
  • 對於value的內存泄漏:每次使用完ThreadLocal中存的變量都要記得remove,這樣就不會造成value 的內存泄漏

於是面試關接着問,既然key采用了弱引用的方式解決內存泄漏,那為什么value不也用弱引用的方式解決內存泄漏,我當時其實都不知道該怎么答了,我照着自己的理解說:對於value的內存泄漏,之所以沒有采用弱引用的方式,是因為不清楚這個Value除了map的引用還是否還存在其他引用,如果不存在其他引用,當GC的時候就會直接將這個value干掉了,而此時我們的ThreadLocal還處於使用期間,就會造成Value為null的錯誤

但是面試官仍然沒有打算放過我,然后接着問,為什么弱引用就能解決內存泄漏問題,其實我覺得當時他的意思是

把Java 的引用數據類型給介紹一下?

我答:Java有強引用、軟引用、弱引用、虛引用。我分別按照自己的理解將這些引用介紹了一下,於是面試官逮這虛引用跟我聊起來了,他說

虛引用有什么用

其實我在Java引用數據類型還有一些了解,所以就介紹了下虛引用,於是面試官說那平常有哪些場景會用到,我說常見的就是NIO通信的時候,因為我之前做過一個項目與硬件數據上傳有關,當時我的服務端就用的NIO,我接着說,比如網卡傳來數據,會先將該數據拷貝到操作系統內存中,如果JVM要用這部分數據,則會再從操作系統的內存中將這部分數據拷貝到JVM內存中,這樣的過程就進行了多次拷貝,且耗時間,因此allocateDirect這樣少一次拷貝的效率會很高,這樣的操作也被稱為零拷貝,NIO底層就用到了零拷貝的原理。在這種零拷貝的情況下,虛引用就誕生了,虛引用通常指向操作系統內存空間的數據,當虛引用要被回收時,就會把該虛引用放到事件隊列里,GC也會時不時檢查隊列,會檢查隊列里的虛引用所指向的內存需不需要被回收,如果需要就直接將其回收,同時將改虛引用出隊,這樣就實現了虛引用監控的作用,實現了通過虛引用清除OS空間里的內存

面試官看我說到了NIO,於是就着NIO開始問我

為什么當時項目用NIO不用IO

其實這個地方我還是能答的,因為我當時項目最開始的確是使用的IO方式接收數據,之后才改成的NIO,於是我回答因為IO底層采用的多路復用機制,效率會比IO高很多,於是面試官接着問

說一說IO多路復用機制是怎樣的

其實到這里我已經感覺到呼吸困難了,我照着自己的理解介紹了IO多路復用機制(當時感覺介紹的很通俗,不夠專業)

於是面試官接着問

那你介紹下select、poll、epoll

select

select(阻塞函數)其實就是將對FD(標志位)數據的集合判斷從原來的用戶態到交給內核態管理(將Rset從用戶態拷貝到了內核態),內核態會快很多,如果判斷有數據

  • 將FD置位,表示此時有數據來了
  • 將select返回,不再阻塞

之后判斷那一個FD被置位了,於是就行取數據處理

select使用的1024的bitmap存數據

缺點:

  • fd_size有限制1024bitmap
  • FDset不可重用
  • 用戶態到內核態的拷貝開銷
  • O(n)再次遍歷

poll

poll(阻塞函數),工作原理與select很相似, 但是poll沒有采用bitmap,采用的pollfd存儲(基於結構體存儲fd)

struct pollfd {
    int fd;
    short events;
    short revents;
}

有數據:

  • pollfd.revents置位
  • poll返回,不再阻塞

執行之后的操作,執行之后再將pollfd.revents設置為0

缺點:

  • 用戶態到內核態的拷貝開銷
  • O(n)再次遍歷

epoll

epoll,最新的一種IO多路復用的函數,用戶態和內核態共享epfd數組,內核用於判斷哪個fd有數據到來,不需要用戶態到內核態的拷貝,不需要輪詢,時間負責度O(1)

有數據:

  • 置位,通過重排置位,將數組中有數據的fd放在前面的位置
  • 返回,有返回值,返回一共有多少個fd觸發了事件,這樣可以實現遍歷復雜度為O(1)

Redis、Ngnix都是使用的epoll,JavaNIO在Linux系統下也是采用的epool實現的

其實到這里我已經答不出來了,因為我操作系統學的其實並不好,上面有些東西也是我之后總結出來補上去的

上面都是我個人的真實經歷,其實有很多點都可以深究去挖掘,我這篇文章的問法可能只是一個岑天大樹的一個小分支,錄制這個視頻的意義就是想跟大家分享分享面經,也是為了告訴大家,知識網絡體系的建立很重要,尤其是對於想要面試大廠的小伙伴本。B站地址:https://space.bilibili.com/476743659


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM