Java-NIO学习小结

一、Java NIO概述

  1. Java NIO由如下三个核心部分组成:
    • Channels 管道;负责连接TCP、UDP、File等进行数据的读写;管道每次读写数据都需要经过Buffers
    • Buffers 缓冲区;负责接收管道读取的数据/向管道传输数据;
    • Selectors 选择器;负责注册的管道,并监听管道的数据流动;调用select方法,会阻塞到管道中事件发生,返回后可以对这个事件进行处理

Selector和Channels的关系

二、Channel

  1. Java NIO的Channel与流类似,区别:流的读写是单向的,而管道的是双工的,既可读又可写,不过在读写切换之前需要调用channel.flip()方法进行读写模式的切换。
    而且 管道可以异步的读写。

  2. Channel的重要实现:

    • FileChannel:文件读写
    • DatagramChannle:UDP网络读写
    • SocketChannel:TCP网络读写
    • ServerSocketChannel:可以向Web服务器一样监听新进来的TCP连接,然后对于每个连接创建响应的SocketChannel读取其中的数据=

    Channel通过Buffer进行数据读写的代码示例:

    
    RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");//定义一个文件
    FileChannel inChannel = aFile.getChannel();//获取文件的管道
    
    ByteBuffer buf = ByteBuffer.allocate(48);//创建一个每次可以读写48个字节的缓冲区
    
    int bytesRead = inChannel.read(buf);   //管道读取数据到缓冲区,每次读满48个字节介绍并返回读取的字节个数
    while (bytesRead != -1) {               //当数据读取完以后返回-1
    
    System.out.println("Read " + bytesRead);
    buf.flip();//反转缓冲区,从写入模式切换到读取模式
    
    while(buf.hasRemaining()){//读取缓冲区里的数据
    System.out.print((char) buf.get());
    }
    
    buf.clear();//缓冲区的数据满后,要clear()/compact()才能继续写入数据
    bytesRead = inChannel.read(buf);
    }
    aFile.close();
  3. Buffer 本质上是一块儿可以写入数据,又可以从中读取数据的内存,被包装成了NIO Buffer对象,并提供了一组方法来访问该块内存。
    • capacity:缓冲区的容量
    • position:位置指示器,初始值都为零。写模式时,从零移动到capacity-1(或limit,即可用空间的限制)的地方,每写入一个值就会,position都会移动到下一个可写入位置的序号;从写模式切换到读模式时,position置零,然后开始移动,直到到上次写入的最后序号limit(即切换时,limit=position)
    • limit:可读/写的限制
  4. Buffer的实现类

    • ByteBuffer
    • MappedByteBuffer
    • CharBuffer
    • DoubleBufferoatBuffer
    • IntBuffer
    • LongBuffer
    • ShortBuffer
  5. 常用方法

    • allocate(int capacity):初始化一个缓冲区,指定其大小
    • put()

三、Scatter和Gather

分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

ByteBuffer[] bufferArray = { header, body };

channel.read(bufferArray);

聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

//write data into buffers

ByteBuffer[] bufferArray = { header, body };

channel.write(bufferArray);

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。所以如果需要指定数据到指定的Channel中,必须使用数据的长度来定义相应Channel的容积

四、Selector 选择器

发布了45 篇原创文章 · 获赞 17 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览