NIO是标准IO的一个替代方案。标准的IO API你是和字符流以及字节流打交道。而NIO你则和CHANNELS和BUFFERS打交道。数据总是从CHANNEL到BUFFER,再从BUFFER到CHANNEL。JAVA NIO允许你进行异步的IO.一个线程可以访问CHANNEL读取数据到BUFFER。而CHANNEL在读数据到BUFFER的时候,线程是可以做其他事情的。一旦数据读完。线程可以继续处理它。同样道理可以用于些CHANNEL。
NIO还包含了SELETOR的概念。一个选择器是一个可以监听多个CHANNEL并发布事件。
NIO有更多的组件,然而CHANNELS、BUFFERS、SELETOR 组成了最核心的API。我觉得,其余的组件比如PIPE、FILELOCK仅仅是用于连接这三个核心组件的工具类。因此在进行概览的时候,我们集中关注于这三个组件。
CHANNEL有点像流,里面的数据可以读到到BUFFER,也可以将BUFFER的数据写到CHANNEL。有很多CHANNEL和BUFFER的类型。以下是一些主要的CHANNEL。
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
MappedByteBuffer
用于连接内存映射的文件,此处不提。
SELECTORS允许单线程可以处理多个CHANNEL,这方便于应用包含多开启连接而每个连接的通讯都很低的情况。比如聊天服务器。
CHANNEL要注册到SELECTOR,需要调用select()方法。这个方法会进行阻塞,直到注册的CHANNEL发生了事件。一旦方法有了返回,线程就可以开始处理事件。事件的例子比如,新增链接、数据接收等。
BUFFER介绍
典型的数据读写要经历以下三步骤:
(1)写数据,这时候buffer会保持对数据写入量的跟踪。
(2)一旦你开始要进行数据的读取,你就要调用buffer.filp()从写模式到读模式。
(3)读数据。
(4)一旦读完数据你需将新的数据再次写入BUFFER,你要调用clear或者compact清楚所有的BUFFER或者清理那些已经读过的数据。未读的数据则搬移到BUFFER的开始,而新数据将会接着往下写。
BUFFER的
容量capacity,位置和限制的含义取决于Buffer处于读或者写模式。而容量的含义则是一样的。
位置position,写得时候0-x。 读的时候X-0
限制limit,写的时候是等于容量,读的时候等于实际容量。
BUFFER本质上是一可读可写的内存块。可以写完再读。这个内存被封装成Buffer对象,提供了一些方法使得对内存块的操作更加容易。
分配BUFFER
给BUFFER写东西,BUFFER的写等于CHANNEL的读。CHANNEL的写等于BUFFER的读。
NIO支持Scatter和Gatter模式,Scatter意味着一个Channel对应多个Buffer来读。而Gatter意味着多个Buffer来写一个Channel。
Channel和Channel是可以复制的,transferFrom 很transferTo