Java NIO提供了与标准IO不同的IO工作方式:
Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Selectors(选择器):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
Buffer:
为什么需要buffer:计算机CPU已经不是程序运行的瓶颈,程序大多数时候都在等待数据,向网卡/硬盘等硬件设备读写数据,因此I/O操作具有很大的性能优化空间。使用缓存进行批量的I/O操作可以减少CPU运算与I/O之间的切换,提高CPU运算模块的利用率。
程序标准buffer:
由于程序不能直接操纵硬件,早期程序操作内存如下图:
在现代计算机系统中,采用虚拟内存地址技术,将程序使用的内存映射到物理内存与高速磁盘中,比如linux中的swap空间,windows中的虚拟内存配置等。由此带来了内存操作的优化:
java buffer:
类名: java.nio.buffer , 子类:
buffer要素:容量(capacity,buffer申请的内存大小),大小(limit 可读写的大小),位置(get,put方法所在的下标),标记(mark),读写(get,put)。
大小关系: 0<=mark<=position<=limit<=capacity
Java buffer的特性:
· buffer可以是只读的,也可以是可读写的,由asReadOnlyBuffer()转化。
· buffer可以以数组形式做转存:buffer.wraps()
ByteBuffer与其他buffer有一定区别:
1. byteBuffer可以与其他基本类型buffer数据转化,它具有putChar(), getChar()等方法实现单个数值的转化,又有asCharBuffer()方法将整个缓存区转为charBuffer使用。
2. byteBuffer允许直接使用系统内存,这样的内存不受JVM垃圾回收的管理,使用时候需要注意回收内存。ByteBuffer.allocateDirect(int capacity)。
样例代码:
Buffer常用操作:
buffer.position() 无参数,返回当前position位置;int X参数,将position置为X
buffer.get() 无参数,取出当前position的值并position++;int X参数,取出position位置X的值
buffer.put() 1参数,写入当前position的值并position++;2参数,写入position位置X的值
buffer.flip() 将position置为0,limit=position
buffer.compact() 若position之前有值将position之前的值抛弃,将position置为limit-position+1 即把position与limit之间的空间放到0 - position中间。
buffer.clear() position置为0,limit=capacity
buffer.hasRemaining() 返回true表示下一位的值不为空,用来判断position - limit 之间是否有值
buffer.remaining() 返回当前位置到limit之间有值的个数