Java NIO核心组成部分

来源:互联网 发布:php记录访客信息 编辑:程序博客网 时间:2024/06/06 01:11
Java NIO 核心部分


Channels   通道
Buffers  缓冲区
Selectors 选择器


基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示: 

Channel
Channel的实现: (涵盖了UDP 和 TCP 网络IO,以及文件IO)

FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
读数据:

int bytesRead = inChannel.read(buf);
写数据:

int bytesWritten = inChannel.write(buf);  
还有部分的使用,如配置Channel为阻塞或者非阻塞模式,以及如何注册到Selector上面去,参考Selector部分;

Buffer

Buffer实现: (byte,  char、short, int, long, float, double )

ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer

ShortBuffer


Buffer使用
读数据
flip()方法
将Buffer从写模式切换到读模式
调用flip()方法会将position设回0,并将limit设置成之前position的值。
buf.flip();
  (char) buf.get()
读取数据
Buffer.rewind()
将position设回0,所以你可以重读Buffer中的所有数据
limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)
Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用
Buffer.reset()方法,恢复到Buffer.mark()标记时的position
一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。
clear()方法会:
清空整个缓冲区。
position将被设回0,limit被设置成 capacity的值
compact()方法:
只会清除已经读过的数据;任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
将position设到最后一个未读元素正后面,limit被设置成 capacity的值
写数据
buf.put(127);  

Buffer的三个属性

capacity:含义与模式无关;Buffer的一个固定的大小值;Buffer满了需要将其清空才能再写;
ByteBuffer.allocate(48);该buffer的capacity为48byte
CharBuffer.allocate(1024);该buffer的capacity为1024个char 
position:含义取决于Buffer处在读模式还是写模式(初始值为0,写或者读操作的当前位置)
写数据时,初始的position值为0;其值最大可为capacity-1
将Buffer从写模式切换到读模式,position会被重置为0
limit:含义取决于Buffer处在读模式还是写模式(写limit=capacity;读limit等于最多可以读取到的数据)
写模式下,limit等于Buffer的capacity
切换Buffer到读模式时, limit表示你最多能读到多少数据;


Selector


概述
    Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。 要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。 
使用

创建:Selector selector = Selector.open();  
注册通道:
channel.configureBlocking(false);  
与Selector一起使用时,Channel必须处于非阻塞模式
这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式(而套接字通道都可以)
SelectionKey key = channel.register(selector, Selectionkey.OP_READ); 
第二个参数表明Selector监听Channel时对什么事件感兴趣
SelectionKey.OP_CONNECT  SelectionKey.OP_ACCEPT  SelectionKey.OP_READ SelectionKey.OP_WRITE
可以用或操作符将多个兴趣组合一起
SelectionKey
包含了interest集合 、ready集合 、Channel 、Selector 、附加的对象(可选)
int interestSet = key.interestOps();可以进行类似interestSet & SelectionKey.OP_CONNECT的判断
使用:
select():阻塞到至少有一个通道在你注册的事件上就绪了
selectNow():不会阻塞,不管什么通道就绪都立刻返回
selectedKeys():访问“已选择键集(selected key set)”中的就绪通道
close():使用完selector需要用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效