Buffer是个啥?

Buffer 即缓冲区,用来暂存输入输出数据的区域。Buffer对象是一份固定数量的数据的容器,实质上是一个数组。但是一个缓冲区不仅仅是一个数组,缓冲区提供了对数据的结构化访问,还可以跟踪系统的读/写进程。
 
在 Java传统 IO 中,数据直接写入或者将数据直接读到 Stream 对象中。
而在 NIO 中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,都是将它放到缓冲区中。
NIO中的Buffer主要用于与NIO通道(channel)进行交互,数据是从通道读入缓冲区,从缓冲区写入通道中的。
 

继承关系图

Buffer作为一个容器用来存储数据的,根据存储数据类型的不同,分为以下七种:
ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer

主要属性

// 标记、位置、限制、容量遵守以下不变式:
// 0<=mark<=position<=limit<=capacity // 标记是一个位置索引,可以在之后设置位置为标记值再次读写。
private int mark = -1; // 位置,表示缓冲区中正在操作数据的位置。
// 可以把position理解成一个指针,指向的位置就是操作的位置。
private int position = 0; // 界限,表示缓冲区中可以操作数据的大小。
private int limit; // 容量,表示缓冲区中最大存储数据的容量。一旦声明,不可改变。
private int capacity; // 指向缓冲区的地址
long address;

构造方法

// 创建一个具有给定标记、位置、限制和容量的新缓冲区
Buffer(int mark, int pos, int lim, int cap) {
// 缓冲区的初始化容量不能小于0
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
// 初始化缓冲区容量
this.capacity = cap;
// 初始化缓冲区限制,设置最新的缓冲区Buffer
limit(lim);
position(pos);
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}

关键方法解析

position方法:设置当前操作位置

public final Buffer position(int newPosition) {
// 当前操作位置不能超过limit大小,不能小于0
if ((newPosition > limit) || (newPosition < 0))
throw new IllegalArgumentException();
position = newPosition;
// 如果标记位置大于正在操作位置,那么将mark设置为-1。
if (mark > position) mark = -1;
return this;
}

limit方法:设置缓冲区限制

public final Buffer limit(int newLimit) {
// newLimit大小不能超过缓冲区最大容量capacity,不能小于0
if ((newLimit > capacity) || (newLimit < 0))
throw new IllegalArgumentException();
limit = newLimit;
// 正在操作数据的位置不能大于界限
if (position > limit) position = limit;
// 如果标记位置大于界限,那么将mark设置为-1。
if (mark > limit) mark = -1;
return this;
}

reset方法:将缓冲区Buffer的位置position设置为以前临时备忘变量mark存储的位置

public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
clear方法:清除缓冲区,clear方法并没有将之前的数据真的清除,当读数据前调用flip方法后,limit会限制不让使用旧数据。
public final Buffer clear() {
position = 0;
// 虽然将limit数值设置为最大容量,只是为了正常使用buffer
limit = capacity;
mark = -1;
return this;
}

flip方法: 反转此缓冲区,在进行写完去读的时候使用,说白了,让你开始读的时候从初始位置0开始。

public final Buffer flip() {
// 将position置为0,其实就是切换读写模式
limit = position;
position = 0;
mark = -1;
return this;
}

rewind方法:重绕此缓冲区,在通道写入或者获取之前调用

public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}

remaining方法:返回当前的缓冲区Buffer中剩余元素的数量

public final int remaining() {
return limit - position;
}

总结

1、Buffer中所有的方法操作,都遵守以下不变式:
 0<=mark<=position<=limit<=capacity
2、flip方法,让数据开始读的时候从初始位置0开始。
3、clear方法其实是个障眼法,并没有清除之前数据内容。

盘一盘 NIO (一)—— Buffer源码解析的更多相关文章

  1. Git8.3k星,十万字Android主流开源框架源码解析,必须盘

    为什么读源码 很多人一定和我一样的感受:源码在工作中有用吗?用处大吗?很长一段时间内我也有这样的疑问,认为哪些有事没事扯源码的人就是在装,只是为了提高他们的逼格而已. 那为什么我还要读源码呢?一刚开始 ...

  2. Python优秀开源项目Rich源码解析

    这篇文章对优秀的开源项目Rich的源码进行解析,OMG,盘他.为什么建议阅读源码,有两个原因,第一,单纯学语言很难在实践中灵活应用,通过阅读源码可以看到每个知识点的运用场景,印象会更深,以后写代码的时 ...

  3. Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  4. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  5. Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. Scala 深入浅出实战经典 第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. Netty 4源码解析:服务端启动

    Netty 4源码解析:服务端启动 1.基础知识 1.1 Netty 4示例 因为Netty 5还处于测试版,所以选择了目前比较稳定的Netty 4作为学习对象.而且5.0的变化也不像4.0这么大,好 ...

  8. Netty5客户端源码解析

    Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...

  9. Netty5服务端源码解析

    Netty5源码解析 今天让我来总结下netty5的服务端代码. 服务端(ServerBootstrap) 示例代码如下: import io.netty.bootstrap.ServerBootst ...

随机推荐

  1. xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突(当指针访问异常时,应考虑是不是对象未创建)。

    xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突

  2. PHP语句中or的用法

     经常看到这样的语句: $file = fopen($filename, 'r') or die("抱歉,无法打开: $filename"); or在这里是这样理解的,因为在P ...

  3. Xshell为什么连不上虚拟机

  4. MVC WebApi 实现Token验证

    基于令牌的认证 我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户. WEB A ...

  5. CentOS EPEL yum源

    CentOS EPEL yum源 用yum安装软件时,经常发现我们的yum源里面没有该软件,比如htop.网上查到的一个方案是需要自己去wget源码,然后configure,make,make ins ...

  6. mac 下搭建安装 sass

    一.安装系统需要的包 安装Xcode开发工具,它将帮你安装好 Unix 环境需要的开发包 打开 App Store,搜索 Xcode,第一个就是,对了,有4个多G,网速如果不大好,就请先厕所哭会儿吧, ...

  7. AQS原理浅析

    锁是最常用的同步方法之一,在高并发的环境下激烈的锁竞争会导致程序的性能下降,所以我们自然有必要深入的学习一下锁的相关知识. java的内置锁一直都是备受争议的,在JDK 1.6之前,synchroni ...

  8. <<Modern CMake>> 翻译 2.2 CMake 编程

    <<Modern CMake>> 翻译 2.2 CMake 编程 流程控制 CMake有一个 if 语句, 经年累月之后,现在它已经相当复杂. 您可以在 if 语句中使用全大写 ...

  9. 机器学习经典算法之AdaBoost

    一.引言 在数据挖掘中,分类算法可以说是核心算法,其中 AdaBoost 算法与随机森林算法一样都属于分类算法中的集成算法. /*请尊重作者劳动成果,转载请标明原文链接:*/ /* https://w ...

  10. 贪心算法---The best time to buy and sell store-ii

    Say you have an array for which the i th element is the price of a given stock on day i. Design an a ...