NIO分为哪几部分

本文详细介绍了Java NIO中的Buffer缓冲区、Channel通道和Selector选择器,展示了它们在数据读写和IO多路复用中的关键作用,包括Buffer的容量、位置和limit属性,以及Channel和Selector在实现非阻塞IO和效率提升中的关键功能。
摘要由CSDN通过智能技术生成

NIO分为三部分:

(1)、Channel(通道)
(2)、Buffer(缓冲区)
(3)、 Selector(选择器)
下面从缓冲区开始,详细介绍 NIO 的 Buffer(缓冲区)、Channel(通道)、Selector(选择器)三大核心组件。

Channel(通道)

通道(Channel) 在 OIO 中,同一个网络连接会关联到两个流:一个输入流(Input Stream),另一个输出流(OutputStream)。通过这两个流,不断地进行输入和输出的操作。在 NIO 中,同一个网络连接使用一个通道表示,所有的 NIO 的 IO 操作都是从通道开始的。一个通道类似于 OIO 中的两个流的结合体,既可以从通道读取,也可以向通道写入。

Buffer(缓冲区)

应用程序与通道(Channel)主要的交互操作,就是进行数据的 read 读取和 write 写入。为了
完成如此大任,NIO 为大家准备了第三个重要的组件——NIO Buffer(NIO 缓冲区)。通道的读取,
就是将数据从通道读取到缓冲区中;通道的写入,就是将数据从缓冲区中写入到通道中。缓冲区的使用,是面向流的 OIO 所没有的,也是 NIO 非阻塞的重要前提和基础之一。

Selector(选择器)

首先,回顾一个基础的问题,什么是 IO 多路复用?指的是一个进程/线程可以同时监视多个文
件描述符(一个网络连接,操作系统底层使用一个文件描述符来表示),一旦其中的一个或者多个
文件描述符可读或者可写,系统内核就通知该进程/线程。在 Java 应用层面,如何实现对多个文件
描述符的监视呢?需要用到一个非常重要的 Java NIO 组件——Selector 选择器。
选择器的神奇功能是什么呢?它一个 IO 事件的查询器。通过选择器,一个线程可以查询多个
通道的 IO 事件的就绪状态。实现 IO 多路复用,从具体的开发层面来说,首先把通道注册到选择器中,然后通过选择器内部的机制,可以查询(select)这些注册的通道是否有已经就绪的 IO 事件(例如可读、可写、网络连接完成等)。一个选择器只需要一个线程进行监控,换句话说,我们可以很简单地使用一个线程,通过选择器去管理多个通道。这是非常高效的,这种高效来自于 Java 的选择器组件 Selector,以及其背后的操作系统底层的 IO 多路复用的支持。与 OIO 相比,使用选择器的最大优势:系统开销小,系统不必为每一个网络连接(文件描述符)创建进程/线程,从而大大减小了系统的开销。

详解 NIO Buffer 类及其属性

NIO 的 Buffer(缓冲区)本质上是一个内存块,既可以写入数据,也可以从中读取数据。NIO
的 Buffer 类,是一个抽象类,位于 java.nio 包中,其内部是一个内存块(数组)。
NIO 的 Buffer 与普通的内存块(Java 数组)不同的是:NIO Buffer 对象,提供了一组更加有
效的方法,用来进行写入和读取的交替访问。需要强调的是:Buffer 类是一个非线程安全类。

Buffer 类

Buffer 类是一个抽象类,对应于 Java 的主要数据类型,在 NIO 中有 8 种缓冲区类,分别如下:
ByteBuffer 、 CharBuffer 、 DoubleBuffer 、 FloatBuffer 、 IntBuffer 、 LongBuffer 、 ShortBuffer 、
MappedByteBuffer。 前 7 种 Buffer 类型,覆盖了能在 IO 中传输的所有的 Java 基本数据类型。第 8 种类型
MappedByteBuffer 是专门用于内存映射的一种 ByteBuffer 类型。
实际上,使用最多的还是 ByteBuffer 二进制字节缓冲区类型,后面会看到。

Buffer 类的重要属性

Buffer 类在其内部,有一个 byte[]数组内存块,作为内存缓冲区。为了记录读写的状态和位置,Buffer 类提供了一些重要的属性。其中,有三个重要的成员属性:capacity(容量)、position(读写位置)、limit(读写的限制)。除此之外,还有一个标记属性:mark(标记),可以将当前的position 临时存入mark 中;需要的时候,可以再从 mark 标记恢复到 position 位置。

  1. capacity 属性
    Buffer 类的 capacity 属性,表示内部容量的大小。一旦写入的对象数量超过了 capacity 容量,缓冲区就满了,不能再写入了。Buffer 类的 capacity 属性一旦初始化,就不能再改变。原因是什么呢?Buffer 类的对象在初始化时,会按照 capacity 分配内部的内存。在内存分配好之后,它的大小当然就不能改变了。再强调一下,capacity 容量不是指内存块 byte[]数组的字节的数量。capacity 容量指的是写入的
    数据对象的数量。
    前面讲到,Buffer 类是一个抽象类,Java 不能直接用来新建对象。使用的时候,必须使用 Buffer
    的某个子类,例如使用 DoubleBuffer,则写入的数据是 double 类型,如果其 capacity 是 100,那么
    我们最多可以写入 100 个 double 数据。
  2. position 属性
    Buffer 类的 position 属性,表示当前的位置。position 属性与缓冲区的读写模式有关。在不同
    的模式下,position 属性的值是不同的。当缓冲区进行读写的模式改变时,position 会进行调整。
    在写入模式下,position 的值变化规则如下:
    (1)在刚进入到写模式时,position 值为 0,表示当前的写入位置为从头开始。
    (2)每当一个数据写到缓冲区之后,position 会向后移动到下一个可写的位置。
    (3)初始的 position 值为 0,最大可写值 position 为 limit– 1。当 position 值达到 limit时,缓冲区就已经无空间可写了。
    在读模式下,position 的值变化规则如下:
    (1)当缓冲区刚开始进入到读模式时,position 会被重置为 0。
    (2)当从缓冲区读取时,也是从 position 位置开始读。读取数据后,position 向前移动到下一个可读的位置。
    (3)position 最大的值为最大可读上限 limit,当 position 达到 limit 时,表明缓冲区已经无数据可读。
    起点在哪里呢?当新建一个缓冲区时,缓冲区处于写入模式,这时是可以写数据的。数据写入后,如果要从缓冲区读取数据,这就要进行模式的切换,可以使用(即调用)flip 翻转方法,将缓冲区变成读取模式。在这个 flip 翻转过程中,position 会进行非常巨大的调整,具体的规则是:position 由原来的写入位置,变成新的可读位置,也就是 0,表示可以从头开始读。flip 翻转的另外一半工作,就是要调整 limit 属性。
  3. limit 属性
    Buffer 类的 limit 属性,表示读写的最大上限。limit 属性,也与缓冲区的读写模式有关。在不同的模式下,limit 的值的含义是不同的。在写模式下,limit 属性值的含义为可以写入的数据最大上限。在刚进入到写模式时,limit 的值会被设置成缓冲区的 capacity 容量值,表示可以一直将缓冲区的容量写满。在读模式下,limit 的值含义为最多能从缓冲区中读取到多少数据。
    一般来说,是先写入再读取。当缓冲区写入完成后,就可以开始从 Buffer 读取数据,可以使
    用 flip 翻转方法,这时,limit 的值也会进行非常大的调整。具体如何调整呢?将写模式下的 position 值,设置成读模式下的 limit 值,也就是说,将之前写入的最大数量,作为可以读取的上限值。在 flip 翻转时,属性的调整,将涉及 position、limit 两个属性,这种调整比较微妙,不是太好理解,举一个简单例子:
    首先,创建缓冲区。刚开始,缓冲区处于写模式。position 为 0,limit 为最大容量。然后,向缓冲区写数据。每写入一个数据,position 向后面移动一个位置,也就是 position 的值加 1。假定写入了 5 个数,当写入完成后,position 的值为 5。这时,使用(即调用)flip 方法,将缓冲区切换到读模式。limit 的值,先会被设置成写模式时的 position 值。这里新的 limit 是 5,表示可以读取的最大上限是 5 个数。同时,新的 position 会被重置为 0,表示可以从 0 开始读。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值