天天看點

NIO的組成有哪些——奈學

Buffer:與Channel進行互動,資料是從Channel讀入緩沖區,從緩沖區寫入Channel中的

flip方法 : 反轉此緩沖區,将position給limit,然後将position置為0,其實就是切換讀寫模式

clear方法 :清除此緩沖區,将position置為0,把capacity的值給limit。

rewind方法 : 重繞此緩沖區,将position置為0

DirectByteBuffer可減少一次系統空間到使用者空間的拷貝。但Buffer建立和銷毀的成本更高,不可控,通常會用記憶體池來提高性能。直接緩沖區主要配置設定給那些易受基礎系統的本機I/O 操作影響的大型、持久的緩沖區。如果資料量比較小的中小應用情況下,可以考慮使用heapBuffer,由JVM進行管理。

Channel:表示 IO 源與目标打開的連接配接,是雙向的,但不能直接通路資料,隻能與Buffer 進行互動。通過源碼可知,FileChannel的read方法和write方法都導緻資料複制了兩次!

Selector可使一個單獨的線程管理多個Channel,open方法可建立Selector,register方法向多路複用器器注冊通道,可以監聽的事件類型:讀、寫、連接配接、accept。注冊事件後會産生一個SelectionKey:它表示SelectableChannel 和Selector 之間的注冊關系,wakeup方法:使尚未傳回的第一個選擇操作立即傳回,喚醒的

原因是:注冊了新的channel或者事件;channel關閉,取消注冊;優先級更高的事件觸發(如定時器事件),希望及時處理。

Selector在Linux的實作類是EPollSelectorImpl,委托給EPollArrayWrapper實作,其中三個native方法是對epoll的封裝,而EPollSelectorImpl. implRegister方法,通過調用epoll_ctl向epoll執行個體中注冊事件,還将注冊的檔案描述符(fd)與SelectionKey的對應關系添加到fdToKey中,這個map維護了檔案描述符與SelectionKey的映射。

fdToKey有時會變得非常大,因為注冊到Selector上的Channel非常多(百萬連接配接);過期或失效的Channel沒有及時關閉。fdToKey總是串行讀取的,而讀取是在select方法中進行的,該方法是非線程安全的。

Pipe:兩個線程之間的單向資料連接配接,資料會被寫到sink通道,從source通道讀取

NIO的服務端建立過程:Selector.open():打開一個Selector;ServerSocketChannel.open():建立服務端的Channel;bind():綁定到某個端口上。并配置非阻塞模式;register():注冊Channel和關注的事件到Selector上;select()輪詢拿到已經就緒的事件。

本文來自:奈學開發者社群,如有侵權,請聯系我删除~