初入JavaNIO
NIO愈发流行,不得不了解一下。
Java NIO 由以下几个核心部分组成:
- Channels
- Buffers
- Selectors
NIO比传统的BIO核心区别
NIO采用的是多路复用的IO模型,普通的IO用的是阻塞的IO模型,两个之间的效率肯定是多路复用效率更高
一、缓冲区
Buffer:在NIO中负责数据的存取,数组。
根据不同的数据类型(boolean除外)提供了相应的缓冲区
ByteBuffer
、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FolatBuffer、DoubleBuffer
通过allocate()获取对应的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
缓冲区的两个核心方法
put()//存入数据到缓冲区
get()//获取缓冲区的数据
缓冲区的4个核心属性
- capacity: 容量,表示缓冲区的最大存储容量,一旦申明,不能改变
- limit: 界限,表示缓冲区中可以操作的数据的大小(limit后面的数据不能进行读写)
- position: 位置,表示缓冲区中正在操作数据的位置
- mark: 标记,表示当前position位置,可以通过reset()恢复到mark位置
//创建
ByteBuffer buf = ByteBuffer.allocate(1024);
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//1024
System.out.println(buf.position());//0
//写入数据
buf.put("abcde".getBytes());
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//1024
System.out.println(buf.position());//5
//切换到读取数据模式
buf.flip();
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//5
System.out.println(buf.position());//0
//读取数据
byte[] dst = new byte[buf.limit()];
buf.get(dst);
System.out.println(new String(dst, 0, dst.length));
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//5
System.out.println(buf.position());//5
//重复读
buf.rewind();
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//5
System.out.println(buf.position());//0
//清空缓冲区
buf.clear();
System.out.println(buf.capacity());//1024
System.out.println(buf.limit());//1024
System.out.println(buf.position());//0
//判断剩余空间
if (buf.hasRemaining()) {
System.out.println(buf.remaining());//1024
}
直接缓冲区和非直接缓冲区
创建
ByteBuffer.allocate(1024);//非直接缓冲区,存放在Jvm内存
ByteBuffer.allocateDirect(1024);//直接缓冲区,存放在物理内存,可以提高效率
二、通道
java.nio.channels.Channel
|–FileChannel
|–SocketChannel
|–ServerSocketChannel
|–DatagramChannel
获取通道
- 针对各个通道的类提供getChannel();
- jdk1.7 nio2 针对各个通道的类提供了静态方法FileChannel.open()
- jdk1.7 nio2 的Files工具类newByteChannel();
NIO复制文件
FileInputStream fis = new FileInputStream("1.jpg");
FileOutputStream fos = new FileOutputStream("2.jpg");
FileChannel fisChannel = fis.getChannel();
FileChannel fosChannel = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (fisChannel.read(buffer) != -1) {
buffer.flip();
fosChannel.write(buffer);
buffer.clear();
}
fosChannel.close();
fisChannel.close();
fos.close();
fis.close();
三、选择器
使用NIO完成网络通信的三个核心
- 通道(Channel)负责连接
- 缓冲区(Buffer)负责数据的存取
- 选择器(Selector)是SelectableChannel的多路复用器,用于监控SelectableChannel的IO状况