赞
踩
新IO或非阻塞IO,是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,NIO几个异于传统java IO特点:
1. 从面向流的字节处理到面向缓冲区的数据块处理
2. 基于Selector实现可I/O多路复用
3. 基于Channel可双向传输数据
4. 其它一些高级特性:管道之间数据传输、零拷贝等。
Java NIO 几个核心组件:
主要Buffer:
只画出涉及的部分类类图,图中斜体的类都是抽象类
Buffer
是所有类型缓冲区的父类,根据java的基本类型扩展出了不同类型的缓冲区:ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer
,它们的实现类一般都为HeapXXXBuffer
,当使用XXXBuffer.allocate()
方法进行分配时就是创建HeapXXXBuffer
对象。说明一下缓冲区中几个比较基础、关键的属性:
0<=mark<=position<=limit<=capacity
对缓冲区的一些操作都需要满足以上规则,有些特殊的除外,例如get(int index)
这个操作直接在index位置读取一个元素,正常情况下,读取元素的位置应该position.
缓冲区的实现最终就是对缓冲区中的数组进行操作管理。
向缓冲区写入数据
创建一个容量为10的缓冲区,并向其中插入5个元素(data0-4),这个时候position则指向数组索引为5的位置,而limit指向越界的数组索引10,因为0-9都属性数组范围,可以被写入数据。
从缓冲区读取数据
接着上面写入了5个元素后,现在想从缓冲区中读取写入的元素(一般都是缓冲区满了才会把里面的元素读取出来)。此时通过flip()
方法从写入模式切换到读取模式。当然也可以结合get(int index)
方法循环读取数组hb的所有元素。
创建缓冲区
ByteBuffer.allocate(int capacit); //指定容量
ByteBuffer.wrap(byte[] array); //通过已有数组
往缓冲区写数据
Channel.read(ByteBuffer buffer); //从通道读取数据到缓冲区
put(byte v); //往缓冲区写入一个元素,position位置
put(byte[] src, int offset, int length) //写入一个数组
put(int i, byte x); //在第i位置写入元素x
put(ByteBuffer src); //把一个缓冲区src写到另一个缓冲区
向缓冲区读数据
Channel.write(ByteBuffer buffer); //从Buffer读取数据到Channel
get();//获取position位置元素
get(int i); //获取位置i的元素
get(byte[] dst, int offset, int length);//读取数据并写到dst数组中
getXXX(); //读取元素并包装成char,int,long等类型
写入模式切换到读取模式flip()
limit = position; //最多读limit以前的元素
position = 0; //从第一个元素开始读取
重读缓冲区rewind()
position = 0; //重置position
mark = -1; //抛弃之前的mark
清空缓冲区clear()
有时缓冲区满后,需要进行清除才能继续住里写数据,这个操作将会清空之前缓冲区里的数据,无论是已经读取还是未读取的。
position = 0;
limit = capacity;
mark = -1;
压缩缓冲区compact()
将未读取的数据复制到缓冲区的头部,并调整position,limit为适当的值,不像clear()
把整个缓冲区清空。
标记位置mark()
简单地记录下position的值:mark=position
重置位置reset()
根据之前的标记mark重置position:position=mark
ByteBuffer.allocate(1024)
channel.read(buffer)
通道表示到实体,如硬件设备、文件、网络套接字或可以执行一个或多个不同 I/O 操作(如读取或写入)的程序组件的开放的连接。
主要Channel
以操作对象来区别,则分为两大类:文件通道以及socket通道。
Socket通道有三个,分别是ServerSocketChannel、SocketChannel
和DatagramChannel
,而它们又分别对 应java.net包中的Socket对象ServerSocket、Socket
和DatagramSocket
;Socket通道被实例化时,都会创 建一个对等的Socket对象。Socket通道可以运行非阻塞模式并且是可选择的,非阻塞I/O与可选择性是紧密相连的,这也正是管理阻塞的API要在 SelectableChannel
中定义的原因。设置非阻塞非常简单,只要调用configureBlocking(false)
方法即可。如果需要中 途更改阻塞模式,那么必须首先获得blockingLock()
方法返回的对象的锁。
用来读、写、映射和操纵文件的channel.
可从现有的 FileInputStream
、FileOutputStream
或 RandomAccessFile
对象获得文件通道
czm.java.core.nio.FileChanelTest
可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样
czm.java.core.nio.ServerSocketChannelTest
SocketChannel是一个连接到TCP网络套接字的通道
czm.java.core.nio.SocketChannelTest
DatagramChannel是一个能收发UDP包的通道。因为UDP是无连接的网络协议,所以不能像其它通道那样读取和写入。它发送和接收的是数据包。
可以将DatagramChannel“连接”到网络中的特定地址的。由于UDP是无连接的,连接到特定地址并不会像TCP通道那样创建一个真正的连接。而是锁住DatagramChannel ,让其只能从特定地址收发数据。它是无连接的,它既可以作为服务器,也可以作为客户端。
czm.java.core.nio.DatagramChannelTest
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程
czm.java.core.nio.DatagramChannelClientDemo
czm.java.core.nio.DatagramChannelServerDemo
美团点评-NIO浅析:https://zhuanlan.zhihu.com/p/23488863
Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式:http://www.jasongj.com/java/nio_reactor/
Java NIO 浅析:https://www.zybuluo.com/dodola/note/153662
理解Java NIO:http://www.open-open.com/lib/view/open1371349692734.html
java并发编程网:http://ifeve.com/java-nio-all/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。