2.偏頭痛楊的中高階java後端面試題攻略系列之io&nio篇(持續更新)
阿新 • • 發佈:2019-02-13
前戲要是以為io就只是用於一個檔案的上傳和下載那你可就大錯特錯了。。。但凡涉及到網路通訊,都離不開io的知識。。。其中NIO是重中之重,想深入學習NIO的童鞋可以去玩netty底層程式碼。切記NIO不能只停留在表面概念階段,這樣被面試官發現會大大的減分。NIO要結合java的網路程式設計知識體系,把程式碼寫出來,加深印象。IO什麼是序列化,反序列化,如何實現序列化?序列化是允許將記憶體中的java物件轉換成與平臺無關的二進位制流,通過硬碟或網路進行傳輸。反序列化是將二進位制流轉換成記憶體中的java物件。預設可通過ObjectOutputStream、ObjectInputStream實現序列化與反序列化。請解釋 Serializable介面、serialVersionID的作用? 必須讓類實現java.io.Serializable介面表示該類的物件支援序列化機制,該介面沒有需要實現的方法,他僅僅告訴java底層該類的物件是可以進行序列化的,並且序列化版本ID由serialVersionUID變數提供。變數serialVersionUID是一個靜態的long型的常量,用於在序列化和反序列化過程中,起到一個辨別類的序列化版本作用,如果兩個類名完全相同,則通過serialVersionUID來判斷該類是否符合要求,如果不行則拋異常。當一個類升級後(對原有類進行修改並編譯成class檔案),只要serialVersionUID保持不變,序列化機制會把他們當成同一個序列化版本。如果不顯式定義則jvm會自動計算建立serialVersionUID,而修改後的類與修改前的類計算結果往往不同,而造成版本不相容問題。我們應該顯式的定義個serialVersionUID,即使在某個物件被序列化之後,它所對應的class檔案被修改了,該物件也依然可以被正確的反序列化。NIO 什麼是NIO?為什麼要使用NIO?傳統IO讀取資料時,如果資料來源沒有資料則會導致執行緒阻塞,都是阻塞式的輸入輸出。傳統IO都是通過位元組的移動來處理,一次只能處理一個位元組,效率不高。JDK1.4新增了一系列改進的IO處理功能,被稱為NIO。NIO採用記憶體對映檔案的方式來處理輸入輸出,NIO將檔案或檔案的一段區域對映到記憶體中,這樣就可以像訪問記憶體一樣訪問檔案了。非阻塞, 效能大幅度提高。Channel(通道)是傳統輸入輸出的模擬,在NIO中所有資料的傳輸都需要通過通道。Channel有個map()方法,可以直接將"一塊資料"對映到記憶體中。傳統IO是面向流的處理,NIO是面向塊的處理。Buffer可以理解成一個容器,本質上是一個數組,資料通過Channel傳輸之前都需要放入到Buffer中,Buffer像竹筒,去Channel裡取水,也允許使用Channel直接將檔案的模組資料對映成Buffer。NIO需要使用Buffer、Channel、Selector結合使用才能方顯威力(具體參考java非阻塞網路程式設計) 把Socket通過Channel註冊到Selector,使用一個執行緒在Selector中輪詢,發現Channel有讀寫的事件,就可以分配給其他執行緒來處理(通常使用執行緒池)。什麼是BIO、NIO、AIO?
NIO的reactor模型是什麼(滴滴面試題)?未完待續。NIO的Selector的內部實現poll與epoll解釋?(滴滴面試題)未完待續。NIO的實現原理?未完待續。
BIO | NIO | AIO |
同步阻塞 | 同步非阻塞 | 非同步非阻塞 |
jdk1.4以前 | jdk1.4 | jdk1.7(NIO.2) |
網路連線時,一個請求一個執行緒,在資料沒有開始傳輸以及資料沒有傳輸完畢前,執行緒要進行阻塞,系統資源消耗大,吞吐量低。 | 網路連線時,多個請求對應一個或少量執行緒,在資料沒有開始傳輸,執行緒不阻塞,而是輪詢check哪個請求的資料來了才去服務哪個請求,需要結合selector以及執行緒池。 | 未完待續 |
BIO方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比較高,併發侷限於應用中 | NIO方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,併發侷限於應用中 | AIO方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作 |