❶ java IO、NIO、AIO詳解
在Java的學習過程中,我們首先需要理解幾個關鍵概念:同步和非同步的概念,以及阻塞與非阻塞的概念。同步意味著用戶線程發起I/O請求後需要等待內核I/O操作完成才能繼續執行,而非同步則是用戶線程在發起請求後仍可繼續執行,內核I/O操作完成時會通知用戶線程或調用其注冊的回調函數。阻塞是指在發起I/O操作後線程需要等待操作完成,而非阻塞則是在發起後立即返回操作狀態,無需等待完成。
Java的IO流基於java.io包實現,提供如File、輸入輸出流等基礎功能,其特點是同步、阻塞的交互方式。雖然簡單直觀,但IO效率和擴展性受限,易成為性能瓶頸。同時,java.net中的Socket、ServerSocket、HttpURLConnection等API也被認為屬於同步阻塞IO類庫。
為解決上述問題,Java引入了NIO框架(java.nio包),在Java 1.4中首次出現,提供了Channel、Selector、Buffer等新抽象,允許構建多路復用、同步非阻塞IO程序。此框架提供了更接近操作系統底層的高性能數據操作方式。隨著Java 7的NIO 2版本(也稱為AIO),引入了非同步非阻塞IO方式,即非同步IO操作基於事件和回調機制,應用操作直接返回,後台處理完成後系統會通知相應線程進行後續工作。
NIO的核心組成部分包括Channel(通道)、Buffer(緩沖區)和Selector(選擇器)。Channel用於讀取和寫入數據,類似於流,但通過Buffer處理數據,同時可雙向操作,更好地反映操作系統真實情況。Buffer作為數據處理的中轉池,用於存儲從通道讀取或准備寫入通道的數據。使用Buffer讀寫數據通常包括寫入數據、翻轉緩沖區、從緩沖區讀取數據以及清除或壓縮緩沖區等步驟。
Selector是一個管理多個Channel的高效工具,允許通過一個線程處理大量並發連接,顯著減少線程切換開銷。創建和使用Selector涉及創建對象、注冊Channel、訪問准備就緒事件集合以及處理就緒的Channel等步驟。Selector的使用提高了線程的利用率和應用的擴展性。
當談到非同步IO(AIO),它在NIO的基礎上更進一步,不依賴於IO操作準備好時的通知,而是當IO操作完成後主動通知應用,從而實現真正的非阻塞操作。AIO簡化了IO編程,使操作更直接,無需等待操作準備,系統會在操作完成後調用預設的回調函數。在Java 1.7中,NIO 2版本引入了AIO,提供了和AsynchronousSocketChannel等非同步通道,以及CompletionHandler介面來處理非同步事件。
總結,Java IO流通過同步阻塞方式實現基礎數據傳輸,NIO通過引入Channel、Buffer和Selector提供更高效、擴展性更強的IO處理方式,而AIO則進一步簡化編程模型,提供非阻塞、非同步的IO操作,顯著提高了應用性能和可擴展性。
❷ BIO、NIO、AIO的區別和原理
本文主要討論了IO模型在Java開發中的應用,特別是BIO、NIO、AIO三種模型的原理與區別。
BIO(Blocking I/O)模型是Java早期使用的IO模型,特點是同步並阻塞,伺服器以一個連接對應一個線程的方式運行,這種方式雖然直觀易懂,但資源消耗大,不適合處理大量並發連接。
NIO(Non-blocking I/O)模型則採用同步非阻塞的方式,伺服器以一個請求對應一個線程的方式運行。當有多個連接同時進行I/O操作時,NIO模型通過多路復用器輪詢並處理請求,這樣可以有效減少線程數量,提高資源利用率。NIO模型適用於連接數量較多且操作較輕的場景。
AIO(Asynchronous I/O)模型,也稱為NIO2,是一種非同步非阻塞的IO模型。在AIO中,客戶端的I/O請求由操作系統先完成,再通知應用啟動線程進行處理。這樣可以充分利用操作系統並發能力,但編程復雜度較高。AIO適用於連接數量多且操作較為復雜、資源密集型的場景,如相冊伺服器。
對於BIO模型的改進,可以採用多線程處理邏輯部分,將線程池與BIO模型結合,提高效率。在多CPU環境中,可以將Reactor模型分解為兩部分,進一步優化性能。
NIO模型的改進主要集中在優化多路復用器的實現,以及利用epoll或select等高效事件管理機制,提高性能。同時,避免在連接沒有數據時產生過多無用線程,降低資源消耗。
AIO模型則通過非同步調用API的read或write方法,實現更高效的數據傳輸。在進行讀寫操作時,操作系統會主動通知應用程序,避免長時間阻塞,提高系統響應速度。AIO模型在處理大量並發連接和資源密集型操作時,能夠顯著提升性能。
IO處理流程方面,BIO模型中,線程會一直阻塞在讀寫操作上,直到數據完全傳輸。NIO模型使用多路復用器輪詢並處理就緒的channel,實現更高效的並發處理。AIO模型中,應用調用非阻塞的accept方法,等待數據准備完成後回調處理響應操作。
綜上所述,BIO、NIO和AIO模型在處理並發IO操作時各有優勢,選擇合適的模型取決於具體的應用場景和性能需求。了解這些模型的原理與實現方式,有助於在實際開發中做出更恰當的技術決策。
❸ Java NIO與IO的區別和比較
Java NIO和IO的主要區別如下:
1.NIO 的創建目的是為了讓 Java 程序員可以實現高速 I/O 而無需編寫自定義的本機代碼。NIO 將最耗時的 I/O 操作(即填充和提取緩沖區)轉移回操作系統,因而可以極大地提高速度。培仿判傳統的IO操作屬於阻塞型,嚴重影響程序的運行速度。
2,。流與塊的比較。原來的大祥 I/O 庫(在 java.io.*中) 與 NIO 最重要的區別是數據打包和傳輸的方式。正如前面提到的,原來的 I/O 以流的方式處理數據,而 NIO 以塊的方式處理數據。
面向流 的 I/O 系統一次一個位元組地處理數據。一個輸入流產生一個位元組的數據,一個輸出流消費配改一個位元組的數據。為流式數據創建過濾器非常容易。鏈接幾個過濾器,以便每個過濾器只負責單個復雜處理機制的一部分,這樣也是相對簡單的。不利的一面是,面向流的 I/O 通常相當慢。
3.一個 面向塊 的 I/O 系統以塊的形式處理數據。每一個操作都在一步中產生或者消費一個數據塊。按塊處理數據比按(流式的)位元組處理數據要快得多。但是面向塊的 I/O 缺少一些面向流的 I/O 所具有的優雅性和簡單性。
❹ java中bio nio aio的區別和聯系
BIO是一個連接一個線程。
NIO是一個請求一個線程。
AIO是一個有效請求一個線程。
先來個例子理解一下概念,以銀行取款為例:
同步 : 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫);
非同步 : 委託一小弟拿銀行卡到銀行取錢,然後給你(使用非同步IO時,Java將IO讀寫委託給OS處理,需要將數據緩沖區地址和大小傳給OS(銀行卡和密碼),OS需要支持非同步IO操作API);
阻塞 : ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回);
非阻塞 : 櫃台取款,取個號,然後坐在椅子上做其它事,等號廣播會通知你辦理,沒到號你就不能去,你可以不斷問大堂經理排到了沒有,大堂經理如果說還沒到你就不能去(使用非阻塞IO時,如果不能讀寫Java調用會馬上返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)
Java對BIO、NIO、AIO的支持:
Java BIO : 同步並阻塞,伺服器實現模式為一個連接一個線程,即客戶端有連接請求時伺服器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。
Java NIO : 同步非阻塞,伺服器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
Java AIO(NIO.2) : 非同步非阻塞,伺服器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知伺服器應用去啟動線程進行處理,
❺ Java NIO和IO的區別
Java NIO和IO的主要區別如下:
1.NIO 的創建目的是為了讓 Java 程序員可以實現高速 I/O 而無需編寫自定義的本機代碼。NIO 將最耗時的 I/O 操作(即填充和提取緩沖區)轉移回操作系統,因而可以極大地提高速度。傳統的IO操作屬於阻塞型,嚴重影響程序的運行速度。
2,。流與塊的比較。原來的 I/O 庫(在 java.io.*中) 與 NIO 最重要的區別是數據打包和傳輸的方式。正如前面提到的,原來的 I/O 以流的方式處理數據,而 NIO 以塊的方式處理數據。
面向流 的 I/O 系統一次一個位元組地處理數據。一個輸入流產生一個位元組的數據,一個輸出流消費一個位元組的數據。為流式數據創建過濾器非常容易。鏈接幾個過濾器,以便每個過濾器只負責單個復雜處理機制的一部分,這樣也是相對簡單的。不利的一面是,面向流的 I/O 通常相當慢。
3.一個 面向塊 的 I/O 系統以塊的形式處理數據。每一個操作都在一步中產生或者消費一個數據塊。按塊處理數據比按(流式的)位元組處理數據要快得多。但是面向塊的 I/O 缺少一些面向流的 I/O 所具有的優雅性和簡單性。
❻ Java中IO與NIO的區別和使用場景
在java2以前,傳統的socket IO中,需要為每個連接創建一個線程,當並發的連接數量非常巨大時,線程所佔用的棧內存和CPU線程切換的開銷將非常巨大。java5以後使用NIO,不再需要為每個線程創建單獨的線程,可以用一個含有限數量線程的線程池,甚至一個線程來為任意數量的連接服務。由於線程數量小於連接數量,所以每個線程進行IO操作時就不能阻塞,如果阻塞的話,有些連接就得不到處理,NIO提供了這種非阻塞的能力。
NIO 設計背後的基石:反應器模式,用於事件多路分離和分派的體系結構模式。
反應器(Reactor):用於事件多路分離和分派的體系結構模式
通常的,對一個文件描述符指定的文件或設備, 有兩種工作方式: 阻塞 與非阻塞 。所謂阻塞方式的意思是指, 當試圖對該文件描述符進行讀寫時, 如果當時沒有東西可讀,或者暫時不可寫, 程序就進入等待 狀態, 直到有東西可讀或者可寫為止。而對於非阻塞狀態, 如果沒有東西可讀, 或者不可寫, 讀寫函數馬上返回, 而不會等待 。
一種常用做法是:每建立一個Socket連接時,同時創建一個新線程對該Socket進行單獨通信(採用阻塞的方式通信)。這種方式具有很高的響應速度,並且控制起來也很簡單,在連接數較少的時候非常有效,但是如果對每一個連接都產生一個線程的無疑是對系統資源的一種浪費,如果連接數較多將會出現資源不足的情況。
另一種較高效的做法是:伺服器端保存一個Socket連接列表,然後對這個列表進行輪詢,如果發現某個Socket埠上有數據可讀時(讀就緒),則調用該socket連接的相應讀操作;如果發現某個 Socket埠上有數據可寫時(寫就緒),則調用該socket連接的相應寫操作;如果某個埠的Socket連接已經中斷,則調用相應的析構方法關閉該埠。這樣能充分利用伺服器資源,效率得到了很大提高。
傳統的阻塞式IO,每個連接必須要開一個線程來處理,並且沒處理完線程不能退出。
非阻塞式IO,由於基於反應器模式,用於事件多路分離和分派的體系結構模式,所以可以利用線程池來處理。事件來了就處理,處理完了就把線程歸還。而傳統阻塞方式不能使用線程池來處理,假設當前有10000個連接,非阻塞方式可能用1000個線程的線程池就搞定了,而傳統阻塞方式就需要開10000個來處理。如果連接數較多將會出現資源不足的情況。非阻塞的核心優勢就在這里。
為什麼會這樣,下面就對他們做進一步細致具體的分析:
首先,我們來分析傳統阻塞式IO的瓶頸在哪裡。在連接數不多的情況下,傳統IO編寫容易方便使用。但是隨著連接數的增多,問題傳統IO就不行了。因為前面說過,傳統IO處理每個連接都要消耗一個線程,而程序的效率當線程數不多時是隨著線程數的增加而增加,但是到一定的數量之後,是隨著線程數的增加而減少。這里我們得出結論,傳統阻塞式IO的瓶頸在於不能處理過多的連接。
然後,非阻塞式IO的出現的目的就是為了解決這個瓶頸。而非阻塞式IO是怎麼實現的呢?非阻塞IO處理連接的線程數和連接數沒有聯系,也就是說處理 10000個連接非阻塞IO不需要10000個線程,你可以用1000個也可以用2000個線程來處理。因為非阻塞IO處理連接是非同步的。當某個鏈接發送請求到伺服器,伺服器把這個連接請求當作一個請求"事件",並把這個"事件"分配給相應的函數處理。我們可以把這個處理函數放到線程中去執行,執行完就把線程歸還。這樣一個線程就可以非同步的處理多個事件。而阻塞式IO的線程的大部分時間都浪費在等待請求上了。
所謂阻塞式IO流,就是指在從數據流當中讀寫數據的的時候,阻塞當前線程,直到IO流可以
重新使用為止,你也可以使用流的avaliableBytes()函數看看當前流當中有多少位元組可以讀取,這樣
就不會再阻塞了。