Java 入门指南:Java NIO —— Buffer(缓冲区)

NIO 的引入

在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。当一个线程执行一个 I/O 操作时,它会被阻塞直到操作完成。这种阻塞模型在处理多个并发连接时可能会导致性能瓶颈,因为需要为每个连接创建一个线程,而线程的创建和切换都是有开销的。

为了解决这个问题,在 Java1.4 版本引入了 NIO(New I/O or Non-Blocking I/O)java.nio。提供了一种基于缓冲区、选择器和非阻塞 IO 模型的 IO 处理方式。相比于之前的 BIO 模型,NIO 可以实现更高的并发、更低的延迟以及更少的资源消耗。

I/O 包和 NIO 已经很好地集成了,java.io 也已经以 NIO 为基础重新实现了,所以现在它可以利用 NIO 的一些特性。例如,java.io 包中的一些类包含以块的形式读写数据的方法,这使得即使在面向流的系统中,处理速度也会更快。

![[BIO vs NIO.png]]
Java NIO 概要介绍:初识 Java NIO

使用 NIO 并不一定意味着高性能,它的性能优势主要体现在高并发和高延迟的网络环境下。当连接数较少、并发程度较低或者网络传输速度较快时,NIO 的性能并不一定优于传统的 BIO 。

Buffer

在 NIO(New Input/Output)模型中,Buffer 是一个重要的概念,与数据打交道,用于在内存中存储数据通过 Channel 将数据传输到 Buffer 缓冲区中,并在缓冲区内进行数据的读写操作

Buffer 本质上是一个数组,可以存储多个相同类型的基本数据类型,如 byte、short、int、long、float、double 等。Buffer 封装了内部的数组,并提供了一些操作该数组的方法。

NIO 提供了多种 Buffer 类型,如

  • ByteBuffer(最常用的 Buffer 类)
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

每种 Buffer 类型对应着不同的基本数据类型,用于存储不同类型的数据。

核心变量

Buffer 除了存储数据外,还保存着四个关键属性:

  1. capacity:表示 Buffer 的容量,即可以存储的最大数据量,容量在创建 Buffer 时就确定,之后不可修改。

  2. position:表示当前 Buffer 中已经处理的数据位置,初始值为 0,必须手动设置。每当进行读写操作时,Position 会自动由相应的 get()put() 函数更新,向前移动

  3. limit:表示 Buffer 中可供访问的数据的最大位置(上界),初始值为 capacity,可以手动设置为 position 或其他值。

  4. mark:表示一个备忘记录,用于在某个特定位置设置 mark,然后在之后的某个时间点通过调用 reset() 方法恢复到该 position。

在进行数据读写操作时,一般需要调用 put() 方法将数据写入 Buffer 中,或者调用 get() 方法从 Buffer 中读取数据。

对于写入操作,由于 position 属性的存在,保证了写入的数据不会覆盖已有的数据;对于读取操作,由于 position 属性的存在,保证了读取的数据不会超出可访问的数据范围。

使用 Buffer 进行数据读写时,需要注意处理好 position 和 limit 属性的值,以及不同类型的 Buffer 之间的数据转换问题。Buffer 并不是线程安全的,使用时需要注意线程同步的问题

常用方法

  1. put():向 Buffer 中写入数据。put() 方法有多个重载形式,它们可以将不同类型的数据写入 Buffer 中。例如 put(byte b)、putInt(int i)、putFloat(float f) 等。

    • put(type value):将指定类型的数据写入到 Buffer 中,position 会自动向前移动。

    • put(byte[] array):将 byte 数组从当前 position 处写入 Buffer,同时会增加 position 的值。

    • put(ByteBuffer src):将 src 中的剩余字节写入 Buffer,同时会增加 position 的值。

  2. get():从 Buffer 中读取数据。get() 方法也有多个重载形式,根据不同的数据类型可以选择对应的 get() 方法进行读取。例如,getInt()、getFloat()、getChar() 等。

    • get():从当前 position 处读取一个字节,并将 position 向前移动。

    • get(byte[] array):将从当前 position 处开始的字节序列读入给定的 byte 数组中,并增加 position 的值。

    • get(ByteBuffer dst):将从当前 position 处开始的字节序列读入给定的 ByteBuffer 中,并增加 position 和 dst 的 position 值。

  3. flip():设置 Buffer 的 limit 属性 为 当前的 position,然后将 position 属性设置为 0。在写入数据后,调用 flip() 方法可以将 Buffer 切换到读模式。

  4. rewind():将 position 属性设置为 0,不改变 limit 属性,可以重复读取 Buffer 中的数据。

  5. clear():将 Buffer 清空,position 和 limit 属性设置为初始值。可以重复写入 Buffer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值