java NIO原理

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

NIO中的重要概念 通道、缓冲区、选择器

  • 通道:类似于流,
    • 但是可以异步读写数据(流只能同步读写),
    • 通道是双向的,(流是单向的),
  • 通道的数据总是要先读到一个buffer 或者 从一个buffer写入,
    • 即通道与buffer进行数据交互。

通道类型:  

  • FileChannel:从文件中读写数据。  
    • FileChannel比较特殊,
    • 它可以与通道进行数据交互,
    • 不能切换到非阻塞模式,
  • DatagramChannel:能通过UDP读写网络中的数据。  
  • SocketChannel:能通过TCP读写网络中的数据。  
    • 套接字通道(SocketChannel)可以切换到非阻塞模式;
  • ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。
    • 对每一个新进来的连接都会创建一个SocketChannel。

缓冲区 - 本质上是一块可以存储数据的内存,被封装成了buffer对象而已!

缓冲区类型:

    • ByteBuffer  
    • MappedByteBuffer  
    • CharBuffer  
    • DoubleBuffer  
    • FloatBuffer  
    • IntBuffer  
    • LongBuffer  
    • ShortBuffer 

 常用方法:

    • allocate() - 分配一块缓冲区  
    • put() -  向缓冲区写数据
    • get() - 向缓冲区读数据  
    • flip() - 将缓冲区从写模式切换到读模式,limit 指向有效数据末尾
    • rewind() - 将缓冲区从写模式切换到读模式,limit 指向capacity 
    • clear() - 从读模式切换到写模式,不会清空数据,
      • 但后续写数据会覆盖原来的数据,
      • 即使有部分数据没有读,也会被遗忘;  
    • compact() - 从读数据切换到写模式,数据不会被清空,
      • 会将所有未读的数据copy到缓冲区头部,
      • 后续写数据不会覆盖,而是在这些数据之后写数据
    • mark() - 对position做出标记,配合reset使用
    • reset() - 将position置为标记值  

缓冲区的一些属性:

  • capacity - 缓冲区大小(容量),
    • 无论是读模式还是写模式,此属性值不会变;
  • position - 写数据时,position表示当前写的位置,
    • 每写一个数据,会向下移动一个数据单元,
    • 初始为0;最大为capacity - 1
    • 切换到读模式时,position会被置为0,表示当前读的位置
  • limit - 写模式下,limit 相当于capacity 表示最多可以写多少数据,
    • 切换到读模式时,limit 等于原先的position,表示最多可以读多少数据。

选择器:相当于一个观察者,

  • 用来监听通道感兴趣的事件,
  • 一个选择器可以绑定多个通道;

通道向选择器注册时,需要指定感兴趣的事件,选择器支持以下事件:

  • SelectionKey.OP_READ表示关注读数据就绪事件 
  • SelectionKey.OP_WRITE表示关注写数据就绪事件 
  • SelectionKey.OP_CONNECT表示关注socket channel的连接完成事件 
  • SelectionKey.OP_ACCEPT表示关注server-socket channel的accept事件 

如果你对不止一种事件感兴趣,

  • 那么可以用“位或”操作符将常量连接起来,如下:
    • int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 

通道向选择器注册时,会返回一个 SelectionKey对象,具有如下属性

  • interest集合
  • ready集合  
  • Channel  
  • Selector
  • 附加的对象(可选) 

用“位与”操作interest 集合和给定的SelectionKey常量,

  • 可以确定某个确定的事件是否在interest 集合中。
    • int interestSet = selectionKey.interestOps();  
       
      boolean isInterestedInAccept  = interestSet & SelectionKey.OP_ACCEPT;
      boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;  
      boolean isInterestedInRead    = interestSet & SelectionKey.OP_READ;  
      boolean isInterestedInWrite   = interestSet & SelectionKey.OP_WRITE;  

       

  • ready 集合是通道已经准备就绪的操作的集合。
    • 在一次选择(Selection)之后,你会首先访问这个ready set。
    • 可以这样访问ready集合: 
      • int readySet = selectionKey.readyOps();
  • 四个方法获取已就绪事件,返回值为boolean:
    • selectionKey.isAcceptable();  
      selectionKey.isConnectable();  
      selectionKey.isReadable();  
      selectionKey.isWritable(); 
  • 可以将一个对象或者更多信息附着到SelectionKey上,
    • 即记录在附加对象上,方法如下:
      • selectionKey.attach(theObject);  
        Object attachedObj = selectionKey.attachment();  

可以通过选择器的select方法获取是否有就绪的通道;

  • int select()  
  • int select(long timeout)  
  • int selectNow()

 

 

转载于:https://my.oschina.net/u/3847203/blog/3010629

你可能感兴趣的:(java NIO原理)