定義:
NIO:是從jdk1.4提出的,本意是New IO(相對於傳統的IO),也叫 No Blocked IO(只相對於網絡IO),它的出現彌補傳統IO的不足,提出了更加高效的方式。
NIO對於網絡IO而言:
jdk1.4:採用了基於select/poll的多路複用IO模型。
jdk1.5及以上:採用了基於epoll的多路複用IO模型。
IO模型可查看:詳解Unix5種IO模型
NIO對於文件IO而言:
NIO對基於文件的IO還是阻塞模型的IO。只有基於網絡IO纔是非阻塞的。
NIO的新特性:
- 基於通道(Channel)和緩衝區(Buffer)操作
- 通道(Channel):一個新的、原始的IO抽象。
- 緩衝區支持(Buffer):爲所有的原始類型提供緩衝區支持。也就是說NIO是強制基於通道和緩衝區操作的。
- 具體操作:數據從通道讀到緩衝區,數據從緩衝區寫入通道(用戶進程角度)。
- 非阻塞(針對網絡IO)
- 提供多路複用、非阻塞的IO操作,即當前線程從通道讀取數組到緩衝區時,或者把緩衝區數據寫入到通道時,線程依然可以進行其他事情。
- 選擇器(selectors)(針對網絡IO)
- 用戶監聽多個通道的事件,如:連接打開,數據到達等,單個線程可監聽多個數據通道。
- 其他
- 提供字符集編碼、解碼解決方案:java.nio.Charset。
- 支持鎖和內存映射文件的文件訪問接口。
- …
核心組件:
- 通道(Channel):Java NIO的數據來源,可以是網絡,也可以是本地磁盤。表示打開到IO設備(文件、套接字)的連接。
- 緩衝區(Buffer):數據讀寫的中轉區。用於容納數據。
- 選擇器(Selectors):異步IO的核心類,可以實現異步非阻塞IO,一個Selectors可以管理多個通道Channel。
一個複製文件的小demo:
/**
* @author YeHaocong
* @decription 一個NIO的Demo,完成對文件的複製
* @Date 2020/5/18 18:52
*/
public class NIOFirstDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test_nio1.txt");
FileOutputStream fos = new FileOutputStream("test_nio1_cp.txt")){
//獲取通道,連接源節點和目標節點,通道本身不存儲任何數據,因此需要緩衝區配合傳輸。
FileChannel fisChannel = fis.getChannel();
//獲取通道,連接源節點和目標節點,通道本身不存儲任何數據,因此需要緩衝區配合傳輸。
FileChannel fosChannel = fos.getChannel();
//創建緩衝區,並分配1024字節。
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//把文件的數據通過通道傳輸寫到ByteBuffer緩衝區中
fisChannel.read(byteBuffer);
//把緩衝區該爲讀模式。
byteBuffer.flip();
//讀取byteBuffer裏面的數據通過輸出流通道寫到文件中
fosChannel.write(byteBuffer);
//清空緩衝區
byteBuffer.clear();
//關閉通道與流
fisChannel.close();
fosChannel.close();
fis.close();
fos.close();
}catch (IOException e){
}
}
}
IO和NIO的區別:
類型 | 面向操作域 | 處理數據 | IO阻塞/非阻塞(基於網絡IO) |
---|---|---|---|
Java IO | 可以面向緩衝區,也可以直接面向數據源,使用流進行傳輸 | 沒有緩衝區的話是直接讀取字節或者字符,並且無法前後移動數據流中的數據 | 阻塞:當一個線程在讀/寫時,當數據完全被讀取/寫入或者數據沒有準備好時,線程不能做其他任務,只能一直阻塞等待,知道數據準備好後才能繼續。 |
Java NIO | 強制通道和緩衝區 | 先讀取數據到緩衝區,並且可以前後移動數據量中的數據 | 非阻塞:當一個線程在讀/寫時,當數據完全被讀取/寫入或者數據沒有準備好時,線程可以做其他任務(控制其他通道),知道數據準備好後再切換回該通道。繼續讀取、寫入。 |