轉載請註明原創出處,謝謝!java
NIO相關知識是不少後續的一些基礎知識,因此今天這篇文章僅僅是簡單介紹,後續會繼續有一到二篇相關NIO內容。數組
Java NIO( New IO) 是從Java 1.4版本開始引入的一個新的IO API,能夠替代標準的Java IO API。NIO與原來的IO有一樣的做用和目的,可是使用的方式徹底不一樣, NIO支持面向緩衝區的、基於通道的IO操做。 NIO將以更加高效的方式進行文件的讀寫操做。緩存
IO | NIO |
---|---|
面向流(Stream Oriented) | 面向緩衝區(Buffer Oriented) |
阻塞IO(Blocking IO) | 非阻塞IO(Non Blocking IO) |
(無) | 選擇器(Selectors) |
- Channels and Buffers(通道和緩衝區):標準的IO基於字節流和字符流進行操做的,而NIO是基於通道(Channel)和緩衝區(Buffer)進行操做,數據老是從通道讀取到緩衝區中,或者從緩衝區寫入到通道中。
- Asynchronous IO(異步IO):Java NIO可讓你異步的使用IO,例如:當線程從通道讀取數據到緩衝區時,線程仍是能夠進行其餘事情。當數據被寫入到緩衝區時,線程能夠繼續處理它。從緩衝區寫入通道也相似。
- Selectors(選擇器):Java NIO引入了選擇器的概念,選擇器用於監聽多個通道的事件(好比:鏈接打開,數據到達)。所以,單個的線程能夠監聽多個數據通道。
**說明:**Asynchronous IO(異步IO)、Selectors(選擇器)等後續文章會繼續介紹的。網絡
經過上面NIO與普通IO的主要區別也能夠看到在基本的IO操做中全部的操做都是基於流進行操做的,而在NIO中全部的操做都是基於緩衝區繼續操做的,全部的讀寫操做都是經過緩存區來進行完成,緩衝區(Buffer)是一個線性的、有序的數據集,只能容納特定的數據類型(基本就是基本數據類型對應的Buffer或者起子類)。dom
緩存區類 | 相關描述 |
---|---|
ByteBuffer | 存儲字節的Buffer |
CharBuffer | 存儲字符的Buffer |
ShortBuffer | 存儲短整型的Buffer |
IntBuffer | 存儲整型的Buffer |
LongBuffer | 存儲長整型的Buffer |
FloatBuffer | 存儲單精度浮點型Buffer |
DoubleBuffer | 存儲雙精度浮點型Buffer |
**備註:**看到上面這幾類是否是想起了JAVA的8種基本數據類型,惟一缺乏boolean對於的類型。異步
第一問:爲何boolean不須要緩存呢? 能夠查閱以前寫的:java二進制相關基礎,裏面有描述規範中數字的內部表示和存儲,boolean所佔位數1bit(取值只有true或者false),因爲字節(byte)是操做系統和全部I/O設備使用的基本數據類型,因此基本都是以字節或者連續的一段字節來存儲表示,因此就沒有boolean,感受也沒有必要boolean類型的緩存操做(像RocketMQ源碼裏面可能把一個Int裏面的某位來表示boolean,其餘位繼續來存儲數據,歡迎關注個人公衆號【匠心零度】,後續RocketMQ源碼類分析的時候如何運用上述技巧進行說明等,其實上面我寫的好幾篇文章都是爲了後續RocketMQ源碼分析作準備的)。源碼分析
讀數據:post
寫數據: buf.put(127);大數據
**備註:**標記、 位置、 限制、 容量遵照如下不變式: 0 <= position <= limit <= capacity。spa
爲了更形象解釋上面重要屬性,準備配上簡單代碼以及圖來進行說明就容易懂了。
//第一步,獲取IntBuffer,經過IntBuffer.allocate操做
IntBuffer buf = IntBuffer.allocate(10) ; // 準備出10個大小的緩衝區
//第二步未操做前輸出屬性值
System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()) ;
//第三步進行設置數據
buf.put(6) ; // 設置一個數據
buf.put(16) ; // 設置二個數據
//第四步操做後輸出屬性值
System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()) ;
//第五步將Buffer從寫模式切換到讀模式 postion = 0 ,limit = 本來position
buf.flip() ;
//第六步操做後輸出屬性值
System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()) ;
複製代碼
程序輸出結果:
position = 0,limit = 10,capacty = 10
position = 2,limit = 10,capacty = 10
position = 0,limit = 2,capacty = 10
複製代碼
查看下圖來進行說明:
通道表示打開到 IO 設備(例如:文件、套接字)的鏈接。若須要使用 NIO 系統,須要獲取用於鏈接 IO 設備的通道以及用於容納數據的緩衝區。而後操做緩衝區,對數據進行處理。Channel 負責傳輸, Buffer 負責存儲。通道是由 java.nio.channels 包定義的。 Channel 表示 IO 源與目標打開的鏈接。Channel 相似於傳統的「流」。只不過 Channel自己不能直接訪問數據, Channel 只能與Buffer 進行交互。
通道都是操做緩存區完成所有的功能的。
經常使用的有入下幾個:
獲取通道的一種方式是對支持通道的對象調用getChannel() 方法。支持通道的類以下:
獲取通道的其餘方式是使用 Files 類的靜態方法 newByteChannel() 獲取字節通道。或者經過通道的靜態方法 open() 打開並返回指定通道。
String info[] = {"歡迎","關注","匠心零度","的","公衆號","謝謝!!"} ;
File file = new File("d:" + File.separator + "testfilechannel.txt") ;
FileOutputStream output = null ;
FileChannel fout = null;
try {
output = new FileOutputStream(file) ;
fout = null;
fout = output.getChannel() ; // 獲得輸出的通道
ByteBuffer buf = ByteBuffer.allocate(1024) ;
for(int i=0;i<info.length;i++){
buf.put(info[i].getBytes()) ; // 字符串變爲字節數組放進緩衝區之中
}
buf.flip() ;
fout.write(buf) ; // 輸出緩衝區的內容
} catch (Exception e) {
e.printStackTrace();
}finally{
if(fout!=null){
try {
fout.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
if(output!=null){
try {
output.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}
複製代碼
程序運行效果:
**說明:**今天只是NIO相關基礎篇一,因此有不少並無涉及到,但願上面說的這樣讓你們有一個新的瞭解,未完待續……
若是讀完以爲有收穫的話,歡迎點贊、關注、加公衆號【匠心零度】。
我的公衆號,歡迎關注,查閱更多精彩歷史!!!