NIO

来源:互联网 发布:阿里云免费ssl 编辑:程序博客网 时间:2024/06/07 02:21

8.6总结

1.NIO

  • NIO,即new I/O,也有人称之为非阻塞I/O。Channel、Buffer、Selector构成了核心的API

2.NIO类库


  • (1)通道Channel
    • 网络数据通过Channel读取和写入。通道与流的不同之处在于通道是双向的,流只是在一个方向上移动,而通道可以用于读、写或二者同时进行。
    • Chinnel的实现
      a、FileChannel 从文件中读写数据。
      b、DatagramChannel 能通过UDP读写网络中的数据。
      c、SocketChannel 能通过TCP读写网络中的数据。
      注:TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议
      d、ServerSocketChannel 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

  • 使用FileChannel读取数据到Buffer中的示例
    这里写图片描述
    这里写图片描述
  • (2)缓冲区Buffer
    • Buffer是一个对象,它包含一些要写入或要读出的数据。缓冲区实质上是一个数组。通常它是一个字节数组(ByteBuffer),除此之外,还有其他一些类型的缓冲区。
    • 使用Buffer读写数据一般遵循以下四个步骤:
      1、写入数据到Buffer
      2、调用flip()方法
      3、从Buffer中读取数据
      4、调用clear()方法或者compact()方法
    • 当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。
      一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。 clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区 未读数据的后面。
    • Buffer的capacity、position、limit
      • capacity
        作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”。只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
      • position
        当写数据到Buffer中时,position表示当前的位置。初始的position值为0。当一个byte、long等数据写到Buffer 后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
        当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
      • limit
        在写模式下,Buffer的limit表示最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
        当切换Buffer到读模式时, limit表示最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,能读到之前 写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)。
    • 常用方法
      • allocate( ):分配一个新的字节缓冲区
      • flip( ):将Buffer从写模式切换到读模式
      • hasRemaining():告知在当前位置和限制之间是否有元素,当且仅当次缓冲区中至少还有一个元素时返回true
      • get( ):读取此缓冲区当前位置的字节,然后该位置递增。
      • clear( )与compact( )方法:
        • 一旦读完Buffer中的数据,需要让Buffer准备好再次被写入。可以通过clear()或compact()方法来完成。
          如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。
        • 如果Buffer中有一些未读的数据,调用clear()方法,数据将“被遗忘”,意味着不再有任何标记会告诉你哪些数据被读过,哪些还没有。
        • 如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。
          compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
  • (3)selector
    • 为了将Channel和Selector配合使用,必须将channel注册到selector上。通过SelectableChannel.register()方法来实现。
    • 与Selector一起使用时,Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。
  • 原创粉丝点击