• Java NIO(一)


    http://wiki.jikexueyuan.com/project/java-nio-zh/java-nio-overview.html

    Java NIO,Non-blocking IO

    02. Java NIO 概览

    NIO包含下面几个核心的组件:

    • Channels
    • Buffers
    • Selectors

    通过Channel,我们即可以从Channel把数据写到Buffer中,也可以吧数据冲Buffer写入到Channel

    有很多的Channel,Buffer类型。下面列举了主要的几种:

    • FileChannel
    • DatagramChannel
    • SocketChanne
    • ServerSocketChannel
    • ByteBuffer
    • CharBuffer
    • DoubleBuffer
    • FloatBuffer
    • IntBuffer
    • LongBuffer
    • ShortBuffer

    NIO实际上还包含一种MappedBytesBuffer,一般用于和内存映射的文件

    选择器允许单线程操作多个通道。如果你的程序中有大量的链接,同时每个链接的IO带宽不高的话,这个特性将会非常有帮助。比如聊天服务器。 下面是一个单线程中Slector维护3个Channel的示意图:

    要使用Selector的话,我们必须把Channel注册到Selector上,然后就可以调用Selector的selectr()方法。这个方法会进入阻塞,直到有一个channel的状态符合条件。

    03. Java NIO Channel通道

    Java NIO Channel通道和流非常相似,主要有以下几点区别:

    • 通道可以度也可以写,流一般来说是单向的(只能读或者写)。
    • 通达可以异步读写。
    • 通道总是基于缓冲区Buffer来读写。

     

    Java NIO中最重要的集中Channel的实现:

    • FileChannel 文件的数据读写
    • DatagramChannel UDP的数据读写
    • SocketChannel TCP的数据读写
    • ServerSocketChannel 监听TCP的链接请求,每个请求会创建一个SocketChannel

    利用FileChannel读取数据到Buffer的例子:

        RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
        FileChannel inChannel = aFile.getChannel();
    
        ByteBuffer buf = ByteBuffer.allocate(48);
    
        int bytesRead = inChannel.read(buf); //把数据读到Buffer中
        while (bytesRead != -1) {
    
          System.out.println("Read " + bytesRead);
          buf.flip();//通过flip()方法把buffer从写模式调整为读模式
    
          while(buf.hasRemaining()){
              System.out.print((char) buf.get());
          }
    
          buf.clear();
          bytesRead = inChannel.read(buf);
        }
        aFile.close();

    04. Java NIO Buffer缓冲区

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

    • 把数据写入buffer;
    • 调用flip;
    • 从Buffer中读取数据;
    • 调用buffer.clear()或者buffer.compact()

    一个Buffer有三个属性是必须掌握的,分别是:

    • capacity容量,最多只能写入容量值得字节,整形等数据。一旦buffer写满了就需要清空已读数据才能继续写入新的数据
    • position位置,
    • limit限制

    capacity 最多只能写入容量值得字节,整形等数据。一旦buffer写满了就需要清空已读数据才能继续写入新的数据

    position: 读写数据开始的位置。写数据时,默认初始化为0,每写入一个字节或整形数据,position移到下一个单元,position最大值为capacity-1。读取数据时,position会归零,每次读取后,position向后移动。

    limit: 

    在写模式,能写入的最大数据量。等同于buffer的容量。

    读模式,limit则代表我们所能读取的最大数据量,他的值等同于写模式下position的位置。

     

    Buffer的方法:

    1.分配内存: allocate()。ByteBuffer.allocate(48)

    2.写入数据到buffer : 

    • 从Channel中写数据到Buffer   inChannel.read(buf)
    • 手动写数据到Buffer,调用put方法 buf.put(127);

    3.从Buffer读数据:

    • 从buffer读数据到channel  inChannel.write(buf)
    • 从buffer直接读取数据,调用get方法  byte aByte = buf.get(); 

    4.翻转 flip() : 把Buffer从写模式切换到读模式。调用flip方法会把position归零,并设置limit为之前的position的值。 也就是说,现在position代表的是读取位置,limit标示的是已写入的数据位置

    5.rewind() 将position置为0,这样我们可以重复读取buffer中的数据。limit保持不变。

    6..clear() and compact() 

    区别:是保留数据还是全部清空。

    clear() : 清空整个Buffer,实际上数据并没有清空,只是标记改了。position重置为0, limit为capacity

    compact() : 可以保留未读的数据,只清空已读取的数据,未被读取的数据会被移动到buffer的开始位置,写入位置则近跟着未读数据之后。

    7. mark() and reset() mark方法可以标记当前的position,通过reset来恢复mark的位置

    8.equals() and compareTo()

    equals() :

    判断两个buffer相对,需满足:

    • 类型相同
    • buffer中剩余字节数相同
    • 所有剩余字节相等

    从上面的三个条件可以看出,equals只比较buffer中的部分内容,并不会去比较每一个元素

    compareTo也是比较buffer中的剩余元素,只不过这个方法适用于比较排序的:

  • 相关阅读:
    codeforces 407B Long Path
    CodeForces 489C Given Length and Sum of Digits...
    hacker cup 2015 Round 1 解题报告
    hacker cup 2015 资格赛
    Codeforces 486(#277 Div 2) 解题报告
    POJ 3468 A Simple Problem with Integers splay
    Codeforces 484(#276 Div 1) D Kindergarten DP
    求平均值问题201308031210.txt
    I love this game201308022009.txt
    QQ
  • 原文地址:https://www.cnblogs.com/jerrice/p/7118284.html
Copyright © 2020-2023  润新知