Java NIO

作者: PINGE_SHIZE | 来源:发表于2018-03-21 16:00 被阅读0次

    一、NIO的概念

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java1.4开始),Java NIO提供了与标准IO不同的IO工作方式。所以Java NIO是一种新式的IO标准,与之间的普通IO的工作方式不同。标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入通道也类似。由上面的定义就说明NIO是一种新型的IO,但NIO不仅仅就是等于Non-blockingIO(非阻塞IO),NIO中有实现非阻塞IO的具体类,但不代表NIO就是NonblockingIO(非阻塞IO)。

    Java NIO 由以下几个核心部分组成:Buffer,Channel,Selector

    传统的IO操作面向数据流,意味着每次从流中读一个或多个字节,直至完成,数据没有被缓存在任何地方。NIO操作面向缓冲区,数据从Channel读取到Buffer缓冲区,随后在Buffer中处理数据。

    二、Buffer的使用

    1,利用Buffer读写数据,通常遵循四个步骤:

    1.把数据写入buffer;

    2.调用flip;

    3.从Buffer中读取数据;

    4.调用buffer.clear()

    当写入数据到buffer中时,buffer会记录已经写入的数据大小。当需要读数据时,通过flip()方法把buffer从写模式调整为读模式;在读模式下,可以读取所有已经写入的数据。当读取完数据后,需要清空buffer,以满足后续写入操作。清空buffer有两种方式:调用clear(),一旦读完Buffer中的数据,需要让Buffer准备好再次被写入,clear会恢复状态值,但不会擦除数据。

    2,Buffer的容量,位置,上限(Buffer Capacity, Position and Limit)

    buffer缓冲区实质上就是一块内存,用于写入数据,也供后续再次读取数据。这块内存被NIO Buffer管理,并提供一系列的方法用于更简单的操作这块内存。一个Buffer有三个属性是必须掌握的,分别是:

    capacity容量

    position位置

    limit限制

    position和limit的具体含义取决于当前buffer的模式。capacity在两种模式下都表示容量。下面有张示例图,描诉了不同模式下position和limit的含义:

    容量(Capacity)

    作为一块内存,buffer有一个固定的大小,叫做capacity容量。也就是最多只能写入容量值得字节,整形等数据。一旦buffer写满了就需要清空已读数据以便下次继续写入新的数据。

    位置(Position)

    当写入数据到Buffer的时候需要中一个确定的位置开始,默认初始化时这个位置position为0,一旦写入了数据比如一个字节,整形数据,那么position的值就会指向数据之后的一个单元,position最大可以到capacity-1。当从Buffer读取数据时,也需要从一个确定的位置开始。buffer从写入模式变为读取模式时,position会归零,每次读取后,position向后移动。

    上限(Limit)

    在写模式,limit的含义是我们所能写入的最大数据量。它等同于buffer的容量。一旦切换到读模式,limit则代表我们所能读取的最大数据量,他的值等同于写模式下position的位置。数据读取的上限时buffer中已有的数据,也就是limit的位置(原position所指的位置)。

    分配一个Buffer(Allocating a Buffer)为了获取一个Buffer对象,你必须先分配。每个Buffer实现类都有一个allocate()方法用于分配内存。下面看一个实例,

    开辟一个48字节大小的buffer:

    ByteBuffer buf = ByteBuffer.allocate(48);

    开辟一个1024个字符的CharBuffer:

    CharBuffer buf = CharBuffer.allocate(1024);

    Buffer的实现类

    其中MappedByteBuffer比较特殊。Java类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段。

    三、Selector使用

    Selector是Java NIO中的一个组件,用于检查一个或多个NIO Channel的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。下面这幅图描述了单线程处理三个channel的情况:

    创建Selector(Creating a Selector)。创建一个Selector可以通过Selector.open()方法:

    Selector selector = Selector.open();

    注册Channel到Selector上:

    channel.configureBlocking(false);

    SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

    channel状态,有四种基础类型可供监听:

    Connect     Accept      Read     Write

    上述的四种就绪状态用SelectionKey中的常量表示如下:

    SelectionKey.OP_CONNECT

    SelectionKey.OP_ACCEPT

    SelectionKey.OP_READ

    SelectionKey.OP_WRITE

    如果对多个事件感兴趣可利用位的或运算结合多个常量,比如:

    int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

    从Selector中选择channel(Selecting Channels via a Selector)

    一旦我们向Selector注册了一个或多个channel后,就可以调用select来获取channel。select方法会返回所有处于就绪状态的channel。

    selectedKeys()

    在调用select并返回了有channel就绪之后,可以通过选中的key集合来获取channel,这个操作通过调用selectedKeys()方法:Set selectedKeys = selector.selectedKeys();

    完整的Selector案例


    相关文章

      网友评论

          本文标题:Java NIO

          本文链接:https://www.haomeiwen.com/subject/ixepqftx.html