总览
-
channel & buffer, buffer的数据能写入channel,同理channel的数据也可写入buffer中。
-
selectors。 单线程同时handle多个channel,借鉴Linux的IO多路复用。
graph TB A[Thread] --> B{Selector} B -->C(Channel) B -->D(Channel) B -->E(Channel) C -->F(Buffer) F -->C D -->G(Buffer) G -->D
Buffer
一块可以先写入再读取的缓冲区,所有的Buffer都可读但不都可写,线程安全。以下表达式永远成立:mark
(标记) <= position
(位置) <= limit
(界限) <= capacity
(容量)。
基本用法
- 将数据写入Buffer;
- 调用buffer.flip(),切换到可读模式;
- 从buffer中读取数据;
- 调用buffer.clear()
清除整个缓冲区
或者 buffer.compact()清除已经读取的区域
。
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get()); // read 1 byte at a time
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
Channel
NIO里面涉及的IO都从Channel开始。Channel有点像stream,但有如下不同:
- 可以对一个channel读和写,Stream只能要么读要么写;
- Channel支持异步读和写;
- Channel总是将数据读到buffer中,或者从buffer中将数据写入channel。