一文看懂Java NIO
传送门
Java NIO
简介
Java Non-blocking IO
JAVA NIO是非阻塞的.线程从channel读取数据到buffer的同时线程可以做其他操作。当数据完全读入到buffer后,线程可以继续对数据进行操作。
Channels and Buffers
在标准的IO API中使用字节流和字符流来进行IO操作。
在NIO中使用Channels和Buffers来进行IO操作。
数据通过channel读入buffer,也可以从buffer写入channel
channels
channel实现了 UTP TCP Server IO
- FileChannel 基于文件读写
- DatagramChannel 基于UDP读写
- SocketChannel 基于TCP读写
- ServerSocketChannel 监听TCP链接,对于每一个链接都建立SocketChannel
demo:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip();
while(buf.hasRemaining()){
System.out.print((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();
Buffer
Buffer的本质是一个可读写的内存块,Buffer对象里包含了可读写的内存块,以及一系列操作。
Buffer中的三个重要属性
- capacity 大小可调的数据存储容器 ,有容量上限,到达上线后不能继续加入数据,只能读取或清空。
- position 读模式时 从此处开始读取数据,写模式时 从此处开始写入数据
- limit 读模式时 此处为最后一个数据的位置,写模式时 此处为capacity容量上限处
Buffer 类型
以下列出了不通种类的Buffer:ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,MappedByteBuffer。
Buffer 创建
调用静态方法allocate()来创建分配空间 创建buffer对象
ByteBuffer buf = ByteBuffer.allocate(48);
读写入buffer
- 使用channel写入数据
int bytesRead = inChannel.read(buf);
- 使用buffer自带方法写入数据
buffer.put("写入的数据")
- 使用channel读入数据
int bytesWritten = inChannel.write(buf);
- 使用get函数读数据
byte aByte = buf.get();
Buffer 使用四个步骤
- 把数据写入Buffer
- 调用buffer.flip() ,从写入模式转成读取模式
- 可以读取Buffer中所有的数据
- 调用 buffer.clear() 清空数据 或 buffer.compact 清除已读数据
Buffer 常用函数
- flip() 切换读写模式
- rewind() 设置position为0,limit不改变
- clear() 清空buffer所有数据都不能在读。此方法使position=0、limit=capacity
- compact() 清空已读数据,复制未读数据作为capacity的头。此方法使position=未读处最后、limit=capacity,此时buffer处于写入模式
- mark() 记录当前的位置(position)
- reset() 回到标记位置
- equals() 两个buffer相等条件:相同的数据类型、空间大小相等、空间内容一样
- compareTo() 此方法比较buffer内数据大小,两个buffer必须类型相同
demo:
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();
Java NIO: Selectors
Selectors 是一个管理工具,可以管理多个channel对操作。
由此一个线程可以操作多个channel。
–待更新