Java的新I/O(java.nio包)

  java.nio包提供了新的I/O功能,主要是定義緩衝器(Buffer)裝數據,並提供通道(channel)連接執行I/O操作的實體以提高輸入輸出的速度,可以理解爲緩衝器裝滿數據,沿通道快速輸入輸出。



一、爲什麼要引入java.nio包?

  Java 平臺傳統的I/O 系統都是基於Byte(字節)和Stream(數據流)的,相應的I/O 操作都是阻塞型的,所以服務器程序也採用阻塞型I/O 進行數據的讀、寫操作。

  本文以TCP長連接模式來討論併發型服務器的相關設計,爲了實現服務器程序的併發性要求,系統由一個單獨的主線程來監聽用戶發起的連接請求,一直處於阻塞狀態;當有用戶連接請求到來時,程序都會啓一個新的線程來統一處理用戶數據的讀、寫操作。

  這種模式的優點是簡單、實用、易管理;然而缺點也是顯而易見的:由於是爲每一個客戶端分配一個線程來處理輸入、輸出數據,其線程與客戶機的比例近似爲1:1,隨着線程數量的不斷增加,服務器啓動了大量的併發線程,會大大加大系統對線程的管理開銷,這將成爲吞吐量瓶頸的主要原因;其次由於底層的I/O 操作採用的同步模式,I/O 操作的阻塞管理粒度是以服務於請求的線程爲單位的,有可能大量的線程會閒置,處於盲等狀態,造成I/O資源利用率不高,影響整個系統的性能。

  對於併發型服務器,系統用在阻塞型I/O 等待和線程間切換的時間遠遠多於CPU 在內存中處理數據的時間,因此傳統的阻塞型I/O 已經成爲制約系統性能的瓶頸。Java1.4版本後推出的NIO 工具包,提供了非阻塞型I/O 的異步輸入輸出機制,爲提高系統的性能提供了可實現的基礎機制。

二、什麼是nio?

  針對傳統I/O 工作模式的不足,NIO 工具包提出了基於Buffer(緩衝區)、Channel(通道)、Selector(選擇器)的新模式;

  Selector(選擇器)、可選擇的Channel(通道)和SelectionKey(選擇鍵)配合起來使用,可以實現併發的非阻塞型I/O 能力。


NIO 工具包的成員


 Buffer(緩衝器)
Buffer 類是一個抽象類,它有7 個子類分別對應於七種基本的數據類型:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和ShortBuffer。

每一個Buffer對象相當於一個數據容器,可以把它看作內存中的一個大的數組,用來存儲和提取所有基本類型(boolean 型除外)的數據。Buffer 類的核心是一塊內存區,可以直接對其執行與內存有關的操作,利用操作系統特性和能力提高和改善Java 傳統I/O 的性能。


 Channel(通道)
Channel 被認爲是NIO 工具包的一大創新點,是(Buffer)緩衝器和I/O 服務之間的通道,具有雙向性,既可以讀入也可以寫出,可以更高效的傳遞數據。

我們這裏主要討論ServerSocketChannel 和SocketChannel,它們都繼承了SelectableChannel,是可選擇的通道,分別可以工作在同步和異步兩種方式下(這裏的可選擇不是指可以選擇兩種工作方式,而是指可以有選擇的註冊自己感興趣的事件)。

當通道工作在同步方式時,它的功能和編程方法與傳統的ServerSocket、Socket 對象相似;
當通道工作在異步工作方式時,進行輸入輸出處理不必等到輸入輸出完畢才返回,並且可以將其感興趣的(如:接受操作、連接操作、讀出操作、寫入操作)事件註冊到Selector 對象上,與Selector 對象協同工作可以更有效率的支持和管理併發的網絡套接字連接。

Selector(選擇器)和SelectionKey(選擇鍵)
各類 Buffer 是數據的容器對象;各類Channel 實現在各類Buffer 與各類I/O 服務間傳輸數據。Selector 是實現併發型非阻塞I/O 的核心,各種可選擇的通道將其感興趣的事件註冊到Selector 對象上,Selector 在一個循環中不斷輪循監視這些註冊在其上的Socket 通道。

SelectionKey 類則封裝了SelectableChannel 對象在Selector 中的註冊信息。當Selector 監測到在某個註冊的SelectableChannel 上發生了感興趣的事件時,自動激活產生一個SelectionKey對象,在這個對象中記錄了哪一個SelectableChannel 上發生了哪種事件,通過對被激活的
SelectionKey 的分析,外界可以知道每個SelectableChannel 發生的具體事件類型,進行相應的處理。

三、nio工作原理

  在併發型服務器程序中使用NIO,實際上是通過網絡事件驅動模型實現的。我們應用Select 機制,不用爲每一個客戶端連接新啓線程處理,而是將其註冊到特定的Selector對象上,這就可以在單線程中利用Selector 對象管理大量併發的網絡連接,更好的利用了系統資源;採用非阻塞I/O 的通信方式,不 要求阻塞等待I/O 操作完成 即可返回(這裏的意思是:不需要完成後才能返回),從而減少了管理I/O 連接導致的系統開銷,大幅度提高了系統性能。


  當有讀或寫等任何註冊的事件發生時,可以從Selector 中獲得相應的SelectionKey ,從SelectionKey 中可以找到發生的事件和該事件所發生的具體的SelectableChannel, 以獲得客戶端發送過來的數據。

  由於在非阻塞網絡I/O 中採用了事件觸發機制,處理程序可以得到系統的主動通知,從而可以實現底層網絡I/O 無阻塞、流暢地讀寫,而不像在原來的阻塞模式下處理程序需要不斷循環等待。使用NIO,可以編寫出性能更好、更易擴展的併發型服務器程序。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章