更新時間:2022-05-17 09:51:42 來源:動力節點 瀏覽2197次
(1)阻塞(Block)和非租用(NonBlock):
阻塞和非阻塞是在進程訪問數據時處理數據是否就緒的一種方式。數據未就緒時阻塞:往往需要等待緩沖區中的數據就緒后再處理其他事情,否則會一直阻塞隊列。在那里等著。
非阻塞:當我們的進程訪問我們的數據緩沖區時,如果數據沒有準備好,則直接返回,無需等待。如果數據準備好了,也直接返回
(2)同步和異步方法:
同步和異步都基于應用程序的私有操作系統處理 IO 事件的方式。比如同步:應用程序直接參與IO讀寫操作。異步:所有IO讀寫都交給操作系統處理,應用只需要等待通知即可。
在同步模式下處理IO事件時,必須阻塞在某個方法上,等待我們的IO事件完成(阻塞IO事件或者通過輪詢IO事件)。對于異步,所有的IO讀寫都交給操作系統來推。這時候,我們可以做其他事情,而不是完成真正的IO操作。當操作完成 IO 時,它會給我們的應用程序一個通知
同步:阻塞直到 IO 事件,阻塞直到讀變為寫。這時候我們根本不能自己動手,讓讀寫方法加到線程中,然后阻塞線程來實現,線程的性能開銷比較大。
塊 IO 和非塊 IO
(1)區別
IO模型 | I | NIO |
---|---|---|
方式 | 從硬盤到內存 | 從內存到硬盤 |
溝通 | 面對溪流(鄉間小路) | 面向緩存(高速公路、多路復用技術) |
處理 | 阻塞 IO(多線程) | 非阻塞 IO(反應堆) |
扳機 | 沒有 | 選擇器(輪詢機制) |
(2)Stream Oriented vs Buffer Oriented
Java NIO 和 IO 的第一個大區別是 IO 是面向流的。NIO 是面向緩沖區的。Java IO是面向流的,意味著每次從流中讀取一個字節,直到所有字節都被讀取完畢,它們不會被緩存到任何地方,而且它不能在流中來回移動數據。如果需要來回移動從流中讀取的數據,則需要先將其緩沖在緩沖區中。Java NIO 的面向緩沖區的方法略有不同。數據被讀入稍后處理的緩沖區,根據需要在緩沖區中來回移動。這增加了處理的靈活性。但是,您還需要檢查緩沖區是否包含您需要處理的所有數據。另外,確保當更多數據被讀入緩沖區時,它不會覆蓋緩沖區中未處理的數據。
(3)阻塞和非阻塞Java IO的各種流都是阻塞的。
這意味著當線程調用 read() 或 write() 時,線程會被阻塞,直到讀取了一些數據,或者數據被完全寫入。在此期間線程不能再做任何事情。Java NIO 的非阻塞模式使線程可以發送請求從通道讀取數據,但它只能獲取當前可用的數據。如果當前沒有可用的數據,它不會得到任何東西。線程可以繼續做其他事情,直到數據可供讀取,而不是保持線程阻塞。非阻塞寫入也是如此。線程請求將一些數據寫入通道,但不需要等待它完全寫入,線程可以在此期間做其他事情。線程通常會花費非阻塞 IO 空閑時間在其他通道上執行 IO 操作,因此單個線程現在可以管理多個輸入和輸出通道(通道)。
(4)選擇器(Selector)
Java NIO的選擇器允許單線程監控多個輸入通道,可以注冊多個通道使用一個選擇器,然后使用單獨的線程“選擇”通道:這些通過已經有傳入可以被處理,或者選擇一個準備好寫入的通道。這種選擇機制使單個線程可以輕松管理多個通道。
(5)NIO和BIO讀取文件
BIO讀取文件
BIO從阻塞流中逐行讀取數據
NIO讀取文件:
通道是數據的載體,緩沖區是數據存放的地方,線程從緩沖區中檢查數據并每次通知通道
(6)處理數據的線程數
NIO:一個線程管理多個連接
BIO:一個線程管理一個連接
在 Java 1.4 之前的 I/O 系統中,提供的都是面向流的 I/O 系統。系統一次處理一個字節的數據,一個輸入流產生一個字節的數據,一個輸出流消耗一個字節 面向流的I/O很慢,Java 1.4引入了NIO,是面向塊的輸入輸出系統。系統以塊為單位進行處理,每個操作都是一步生成或消耗的。對于數據庫,以塊為單位處理數據比以字節為單位處理數據要快得多。
NIO中有幾個核心對象需要掌握:Buffer、Channel、Selector。
緩沖區實際上是一個容器對象,或者更直接地說,它實際上是一個數組。在 NIO 庫中,所有數據都使用緩沖區進行處理。讀取數據時,直接讀入緩沖區;寫入數據時,也寫入緩沖區;每次訪問 NIO 中的數據時,都會將其放入緩沖區。在面向流的 I/O 系統中,所有數據都直接寫入或直接讀取到 Stream 對象中。
在 NIO 中,所有的緩沖區類型都繼承自抽象類 Buffer。最常用的是ByteBuffer。對于Java中的基本類型,基本上都有特定的Buffer類型與之對應。它們之間的繼承關系如下圖所示。
(1)四個屬性的
含義如下:
容量:緩沖區可以容納的最大數據元素數。此容量是在創建緩沖區時設置的,并且永遠無法更改。
上限(Limit):緩沖區的第一個不能被讀寫的元素。換句話說,緩沖區中現有元素的計數。
位置:要讀取或寫入的下一個元素的索引。該位置由相應的 get( ) 和 put( ) 函數自動更新。
標記:要讀取或寫入的下一個元素的索引。該位置由相應的 get( ) 和 put( ) 函數自動更新。
(2)Buffer的常用方法如下:
flip():將寫模式轉換為讀模式
rewind():將位置重置為0,一般用于重復讀。
clear() :
compact(): 將未讀數據復制到緩沖區的頭部。
mark(): reset():mark 可以標記一個位置,reset 可以重置到那個位置。
緩沖區常見類型: ByteBuffer 、 MappedByteBuffer 、 CharBuffer 、 DoubleBuffer 、 FloatBuffer 、 IntBuffer 、 LongBuffer 、 ShortBuffer 。
(3)基本操作
緩沖區基本操作:鏈接
緩沖區分片、緩沖區分配、直接緩沖區、緩沖區映射、緩沖區只讀:鏈接
(4) 緩沖區訪問數據流
存儲數據時,位置為++,停止讀取數據時,
調用flip()。此時limit=position,
讀取數據時position=0,position++,直到limit
clear()清空緩沖區,準備再次寫入(position變為0,limit變為容量)。
通道是一個可以讀寫數據的對象,當然所有的數據都是通過一個Buffer對象來處理的。我們從不直接將字節寫入通道,而是將數據寫入包含一個或多個字節的緩沖區。此外,不是直接從通道讀取字節,而是從通道將數據讀取到緩沖區中,然后從緩沖區中檢索字節。
在 NIO 中,提供了多種通道對象,所有通道對象都實現了 Channel 接口。它們之間的繼承關系如下圖所示:
(1)使用NIO讀取
數據前面我們說過,每當讀取數據時,并不是直接從channel讀取,而是從channel讀取到buffer。所以使用 NIO 讀取數據可以分為以下三個步驟:
1)從 FileInputStream 中獲取 Channel
2)創建 Buffer
3)從 Channel 讀取數據到 Buffer
示例:鏈接
(2)使用NIO寫入數據
使用NIO寫入數據的過程與讀取數據的過程類似。同樣,數據不是直接寫入通道,而是寫入緩沖區,可以分為以下三個步驟:
1)從 FileInputStream中獲取通道
2)創建緩沖區
3)將數據從通道寫入緩沖區
示例:鏈接
(1)阻塞IO模型
在舊的IO包中,serverSocket和socket都是阻塞的,所以一旦出現大規模并發行為,每次訪問都會開啟一個新線程。這時候會有大規模的線程上下文切換操作(因為都在等待,所以資源都被現有線程吃掉了),這個時候不管是等待線程還是處理線程,響應率會下降,并且影響新線程。
(2) NIO
Java NIO 在 jdk1.4 中使用,可以稱為“新 IO”或非阻塞 I/O。下面是java NIO的工作原理:
1)一個專門的線程處理所有的IO事件,負責分發。
2)事件驅動機制:事件到達時觸發,而不是同步監聽事件。
3)線程通信:線程之間通過wait、notify等方式進行通信,確保每一次上下文切換都是有意義的。減少不必要的線程切換。
注意:每個線程的處理流程大概是讀取數據、解碼、計算、編碼、發送響應。
傳統的服務器/客戶端模型將基于 TPR(每個請求的線程)。服務器將為每個客戶端請求創建一個線程。該線程單獨處理客戶端請求。這個模型的一個問題是線程的數量急劇增加。大量線程會增加服務器的開銷。為了避免這個問題,大多數實現都采用線程池模型,并設置線程池中的最大線程數,這帶來了新的問題。如果線程池1線程中有200個線程,有200個用戶在下載大文件,那么第201個用戶的請求無法及時處理,即使第201個用戶只想請求幾個KB大小的頁面。傳統的 Sorvor/Client 模式如下:
NIO 中的非阻塞 IO 采用基于 Reactor 模式的工作方式,IO 調用不會被阻塞,而是注冊具有有趣特性的 IO 事件,例如可讀數據的到來, new Sockets等,系統會在發生hold rate事件時通知我們。Selector,NlO中非阻塞IO的核心設計,是注冊各種IO事件的地方,當這些事件發生時,這個對象告訴我們發生了什么。
當任何注冊的事件發生時,如讀或寫,都可以從Selector中獲取對應的SelectionKey,從SelectionKey中可以找到該事件和該事件發生的具體SelectableChannel,從而獲取客戶端發送的數據。
在 NIO 中使用非阻塞 IO 編寫服務器處理程序需要三個步驟。
(1)將感興趣的事件注冊到Selector對象中
(2)從Selector中獲取感興趣的事件
(3)根據不同的事件進行相應的處理
通過上述介紹,相信大家對Nio原理已經有所了解,大家如果對此比較感興趣,想了解更多相關知識,不妨來關注一下動力節點的NIO視頻教程,視頻教程由淺到深,通俗易懂,很適合沒有基礎的小伙伴學習,希望對大家能夠有所幫助哦。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習