NIO模型全系知识点

NIO有以下几个核心部分组成:

  • Channels
  • Buffers
  • Selectors
Channel和Buffers

所有IO和NIO都从一个Channel开始。Channel有点流的概念。数据都可以从Channel读到Buffer中,也可以从Buffer写到Channel。在这里插入图片描述

Channel主要实现类:
  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel
Channel中的Scatter/Gather

分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个Buffer中。因此Channel将从Channel中读取的数据“分散”到多个Buffer中。
聚集(gather)写入Channel是指在写操作时操作多个Buffer的数据写入同一个Channel,因此,Channel将多个Buffer中的数据“聚集”然后发送到Channel。
scatter/gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的Buffer中,这样你可以方便的处理消息头和消息体。
在这里插入图片描述
在这里插入图片描述
Buffer首先被插入到数组,然后再将数组作为Channel.read()的输入参数。read()方法按照Buffer在数组中的顺序将从channel中读取的数据写入到Buffer中,当一个buffer被写满后,channel紧接着向另一个buffer中写。
Scattering Reads在移动下一个Buffer钱,必须填满当前的Buffer,这意味着他不适用于动态消息。换句话说,如果存在不同的缓存区域,必须将前一个区域填充完毕,Scattering Reads才能正常工作。
在这里插入图片描述
Buffer数组是write()方法的入参,write()方法会按照Buffer在数组中的顺序,将数据写入到Channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量为128byte,但仅仅包涵58byte的数据,那么这58byte的数据会被写入到Channel中。因此与Scattering Reads相反,Gathering Writes能比较好的处理动态消息。

通道之间的数据传输
transferFrom()

FileChannel的transferFrom()方法可以将数据从源通刀传输到FileChannel中。
在这里插入图片描述
方法传入的参数position表示从position处开始向目标文件写入数据,count表示最多传输的字节数。如果源通道的剩余空间小于count个字节,则所传输的字节数要下雨请求的字节数。此外要注意,在SocketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。因此,SocketChannel的实现中,SocketChannel可能不会讲请求的所有数据全部传输到FileChannel中。

transferTo()

transferTo()方法将数据从FileChannel传输到其他的Channel中
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个Channel传到另一个channel中。
在这里插入图片描述

Buffer读写数据一般遵循以下四个步骤:

1.写入数据到Buffer
2.调用flip()方法
3.从Buffer中读取数据
4.调用clear()方法或者compcat()方法

Buffer当中有三个属性:
  • 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。
    当切换到读模式时,limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据。此时limit为你之前写入的最大position。
Buffer的类型

ByteBuffer
MappedByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer

Buffer的分配

要获取Buffer对象首先要进行分配。每一个Buffer类都有一个allocate方法。
在这里插入图片描述

向Buffer中写数据

写数据到Buffer中一共有两种方式:(1)从Channel写到Buffer中。(2)通过Buffer的put()方法写到Buffer里。
在这里插入图片描述

filp()方法

在这里插入图片描述

从Buffer中读取数据

(1)从Buffer读取数据到Channel。(2)使用get()方法从Buffer中读取数据。
在这里插入图片描述

rewind()方法

Buffer.rewind()方法将position设回0,所以你可以重读Buffer中的所有数据。limit不变。

clear()与compact()方法

一旦读完Buffer中的数据,需要让Buffer准备好再次被写入。可以通过clear()或者compact()方法来完成。如果调用的是clear()方法,position将会被设回0,limit被设置成capacity的值。换句话说,Buffer被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里面写数据。如果Buffer中有一些未读数据,调用clear()方法,数据将“被遗忘。重新写入。如果Buffer中仍有未读的数据,且后续还需要这些数据,但此时箱套先写谢写数据,那么使用compact()方法。

mark()与reset()方法

mark可以标记到Buffer中某个特定的position。之后可以通过调用Buffer.reset()恢复到这个position。
在这里插入图片描述

Selector

Selector允许单线程处理多个Channel。如果你打开了多个连接通道,但每个连接流量都很低,使用Selector就会很方便。在这里插入图片描述
要是用Selector,就得向Selector中注册Channel,然后调用他的select()方法。这个方法会一直阻塞到某个注册的通道有事件准备就绪。一旦这个方法返回,线程就可以处理这些事件。事件的例子有:新连接进来,数据接收等。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值