Java NIO概述与Buffer类

NIO概述

NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。

IO与NIO的主要区别

1、面向流与面向缓冲

Java IO和NIO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

2、阻塞与非阻塞IO
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

3、选择器(Selectors)
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

NIO包中的一些核心类

java.nio 主要包含了各种与Buffer相关的类
java.nio.channel 主要包含了与Channel和Selector相关的类和接口
java.nio.charset 主要包含了与编码相关的类接口
java.nio.channels.spi 主要包含了与Channel相关的服务提供者编程接口
javan.nio.charset.spi 主要包含了与charset相关的服务提供者编程接口

Buffer

Buffer是一个抽象类
子类有 ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
核心类
ByteBuffer和CharBuffer
ByteBuffer有一个子类 MappedByteBuffer
MappedByteBuffer类能够将文件直接映射到内存中,那么这样我们就可以像访问内存一样访问文件,非常方便
获取Buffer
static ByteBuffer allocate(int capacity)
分配一个新的字节缓冲区。
static ByteBuffer allocateDirect(int capacity)
分配新的直接字节缓冲区。
二者获取Buffer的区别
1.创建普通Buffer成本低,读写的效率不高
2.因为创建直接Buffer成本高,所以我们一般用在Buffer生存周期较长的时候使用
3.只有ByteBuffer才能够创建直接Buffer,其他的Buffer对象是不能够创建
4.如果创建了直接Buffer但是我又想要使用其他Buffer的功能,可以将ByteBuffer转换成其他Buffer
四个非常重要的概念
capacity: 缓冲区的容量,不可以为负数,一旦创建了就不能够改变
limit: 无效缓冲区的第一个位置索引,limit后面的数据既不可读,也不可写
position : 下一个可以被读取或者写入的缓冲区位置索引
mark: 标记索引,该索引能够用于下次读取或者写入,它只能够在0-position之间
四个系数的关系:
0 < mark < postion < limit < capacity
五个方法
flip(): 将写模式切换为读模式, 将limit的值改为postion的值,同时将postion归0
特点: 就是为下一次数据的读取做好准备
clear(): 将读模式切换为写模式,将limit改为capacity的值,同时将postion归0
特点: 就是为下一次数据的写入做好准备
put(): 相对读取,向Buffer中存储数据
get(): 相对读取,从Buffer中获取数据
hasRemaining(): 判断当前位置和limit之间是否还有元素可处理
绝对读取: get(index) 不会影响position的位置
相对读取: put() get() 会影响,每次读取一次,指针后移
代码演示

public class NIODemo01 {
	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.allocate(10);
		ByteBuffer directBuffer = ByteBuffer.allocateDirect(20);
		CharBuffer charBuffer = CharBuffer.allocate(8);
		System.out.println("capacity:" + buffer.capacity()); // 10
		System.out.println("limit:" + directBuffer.limit()); // 20
		System.out.println("position:" + charBuffer.position()); //0
		charBuffer.put('a');
		charBuffer.put('b');
		charBuffer.put('c');
		System.out.println("capacity:" + charBuffer.capacity()); // 8
		System.out.println("limit:" + charBuffer.limit()); // 8
		System.out.println("position:" + charBuffer.position()); //3
		System.out.println("-----------------------------------------------");
		charBuffer.flip();
		System.out.println("capacity:" + charBuffer.capacity()); // 8
		System.out.println("limit:" + charBuffer.limit()); // 3
		System.out.println("position:" + charBuffer.position()); //0
		System.out.println("-----------------------------------------------");
		char ch = 0;
		ch = charBuffer.get();
		System.out.println(ch);//a
		ch = charBuffer.get();
		System.out.println(ch);//b
		ch = charBuffer.get();
		System.out.println(ch);//c
		System.out.println("capacity:" + charBuffer.capacity()); // 8
		System.out.println("limit:" + charBuffer.limit()); // 3
		System.out.println("position:" + charBuffer.position()); //3
		charBuffer.flip();
		int c = 0;
		while(charBuffer.hasRemaining()){
			c = charBuffer.get();
			System.out.println((char)c);
		}
		System.out.println("-----------------------------------------------");
		charBuffer.clear();
		System.out.println("capacity:" + charBuffer.capacity()); // 8
		System.out.println("limit:" + charBuffer.limit()); // 8
		System.out.println("position:" + charBuffer.position()); //0
		System.out.println(charBuffer.get(1));//绝对读取
		System.out.println("position:" + charBuffer.position());//不改变position
	}
}

你可能感兴趣的:(JavaSE,JAVASE)