NIO是New I/O的簡稱,與舊式的基于流的I/O方法相對,從名字看,它表示新的一套Java I/O标 準。它是在Java 1.4中被納入到JDK中的,并具有以下特性:
NIO是基于塊(Block)的,它以塊為基本機關處理資料 (硬碟上存儲的機關也是按Block來存儲,這樣性能上比基于流的方式要好一些)
為所有的原始類型提供(Buffer)緩存支援
增加通道(Channel)對象,作為新的原始 I/O 抽象
支援鎖(我們在平時使用時經常能看到會出現一些.lock的檔案,這說明有線程正在使用這把鎖,當線程釋放鎖時,會把這個檔案删除掉,這樣其他線程才能繼續拿到這把鎖)和記憶體映射檔案的檔案通路接口
提供了基于Selector的異步網絡I/O

所有的從通道中的讀寫操作,都要經過Buffer,而通道就是io的抽象,通道的另一端就是操縱的檔案。
Java中Buffer的實作。基本的資料類型都有它對應的Buffer
Buffer的簡單使用例子:
總結下使用的步驟是:
1. 得到Channel
2. 申請Buffer
3. 建立Channel和Buffer的讀/寫關系
4. 關閉
下面的例子是使用NIO來複制檔案:
Buffer中有3個重要的參數:位置(position)、容量(capactiy)和上限(limit)
這裡要差別下容量和上限,比如一個Buffer有10KB,那麼10KB就是容量,我将5KB的檔案讀到Buffer中,那麼上限就是5KB。
Buffer中大多數的方法都是去改變這3個參數來達到某些功能的:
public final Buffer rewind() 将position置零,并清除标志位(mark)
public final Buffer clear() 将position置零,同時将limit設定為capacity的大小,并清除了标志mark
public final Buffer flip() 先将limit設定到position所在位置,然後将position置零,并清除标志位mark,通常在讀寫轉換時使用
檔案映射到記憶體
Channel有點類似于流,一個Channel可以和檔案或者網絡Socket對應。
selector是一個選擇器,它可以選擇某一個Channel,然後做些事情。
一個線程可以對應一個selector,而一個selector可以輪詢多個Channel,而每個Channel對應了一個Socket。
當selector調用select()時,會檢視是否有用戶端準備好了資料。當沒有資料被準備好時,select()會阻塞。
selectNow()與select()的差別在于,selectNow()是不阻塞的,當沒有用戶端準備好資料時,selectNow()不會阻塞,将傳回0,有用戶端準備好資料時,selectNow()傳回準備好的用戶端的個數。平時都說NIO是非阻塞的,但是如果沒有資料被準備好還是會有阻塞現象。
當有資料被準備好時,調用完select()後,會傳回一個SelectionKey,SelectionKey表示在某個selector上的某個Channel的資料已經被準備好了。
隻有在資料準備好時,這個Channel才會被選擇。
這樣NIO實作了一個線程來監控多個用戶端。
nio:
1. NIO會将資料準備好後,再交由應用進行處理,資料的讀取/寫入過程依然在應用線程中完成,隻是将等待的時間剝離到單獨的線程中去。
2. 節省資料準備時間(因為Selector可以複用)
aio:
1. 讀完了再通知我(核心記憶體拷貝到工作記憶體到過程)
2. 不會加快IO,隻是在讀完後進行通知
3. 使用回調函數,進行業務處理
NIO是同步非阻塞的
AIO是異步非阻塞的
由于NIO的讀寫過程依然在應用線程裡完成,是以對于那些讀寫過程時間長的,NIO就不太适合。
而AIO的讀寫過程完成後才被通知,是以AIO能夠勝任那些重量級,讀寫過程長的任務。