Java-NIO学习小结

来源:互联网 发布:什么软件下载最好 编辑:程序博客网 时间:2024/06/08 15:20

一、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) {               //当数据读取完以后返回-1System.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 buffersByteBuffer[] bufferArray = { header, body };channel.write(bufferArray);

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

四、Selector 选择器

0 0
原创粉丝点击