Java NIO中的Buffer
简介
Buffer缓冲区,首先要弄明白的是,缓冲区是怎样一个概念。它其实是缓存的一种,我们常说的缓存,包括保存在硬盘上的浏览器缓存,保存在内存中的缓存(比如Redis、memcached)。Buffer是把数据保存在内存中,它本质上用来保存数据的数据结构是数组,例如ByteBuffer是byte数组,IntBuffer是int数组等,对Buffer读写操作,其实是对该数组进行数据存放、读取、清除操作。
Buffer可以理解成是一个容器,可以往容器里写入数据,也可以从容器中读取数据,可以一个字节一个字节的读写,也可以多个字节读写,可以在写的途中切换为读,读到一半又切换到写,等等。。。
Buffer有以下几个属性:
- int mark 标记
- int position 位置
- int limit限制
- int capacity缓冲区的容量,Buffer的容量是固定的,在创建Buffer对象时,制定容量大小。
这几个属性,有什么作用,用在什么地方,为何设置这4个属性。其实不用先理解,在了解reset(),flip()等方法后,就会明白这四个属性的用处。
主要方法
mark、reset
- mark() 在Buffer当前的位置设置标记
public final Buffer mark() {
mark = position;
return this;
}
- reset() 重置Buffer当前的位置为上一次的标记
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
这两个方法的使用场景,从Buffer读取n个字节数据,结果读出来的数据长度比n小(比如网络是拆包问题),这时候会重新再读一次,调用reset()方法。但并不是所有读操作是从位置0开始读,所以在reset()先设置一个标记,调用mark(),最后position = mark,就是从标记的mark位置开始读。
clear,flip, rewind
- clear() 清除Buffer
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
- flip() 反转Buffer,何谓“反转”?在执行完写操作之后,调用调用flip()为下次的读操作准备。
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
使用场景:在进行完写操作后,写入100个字节,所以当前位置position=100,为了下次读操作,读出来是这100个字节数据,所以limit也设为100,限制最多读到100个字节。下次读是从位置0开始,所以position=0。
ByteBuffer buffer = ByteBuffer.allocate(100);
String value = "zhangxh20";
buffer.put(value.getBytes());
buffer.flip();
byte [] arr = new byte[buffer.remaining()];
buffer.get(arr);
String decodeValue = new String(arr);
看下调用flip()操作前后的对比。

如果不做flip操作,读到的将是position到capacity之间的错误内容。

当执行flip()操作之后,它的limit被设置为position,position设置为0,capacity不变,由于读取的内容是从position到limit之间,因此,他能够正确读取到之前写入缓冲区的内容。
- rewind() 重绕Buffer,可以发现rewind()比flip()少了个步骤limit = positon。
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
使用场景:buffer.get(array),把buffer的数据复制到array数组里,会调用buffer的get()方法。get()是从position开始复制,最多limit个,所以只需positon设置为0。
其他特性
不变式
标记、位置、限制和容量值遵守以下不变式:
0 <= 标记 <= 位置 <= 限制 <= 容量
新创建的缓冲区总有一个 0 位置和一个未定义的标记。初始限制可以为 0,也可以为其他值,这取决于缓冲区类型及其构建方式。一般情况下,缓冲区的初始内容是未定义的。
线程安全
Buffer不是线程安全的,被多个线程使用时,需要加同步。
ByteBuffer
byteBuffer字节缓冲区,即每次调用get()或者put()操作的数据最小单位是byte,理IntBuffer、LongBuffer、DoubleBuffer以此类推。例如LongBuffer put()最小的单位是8个字节的long数据。日常开发中,ByteBuffer使用的会比较多,其他类型Buffer很少使用。
事实上ByteBuffer也可以用来表示其他类型Buffer,比如IntBuffer的get(),可以用ByteBuffer的getInt(),两个实现效果一样。
堆内存和直接内存
Buffer在创建时,必须指定容量大小,还有分配内存的类型,有两种堆内存和直接内存,直接可以理解为堆外的内存空间,区别就是,直接内存是不受GC管理
参考资料
- 《Netty权威指南》
Java NIO中的Buffer的更多相关文章
- Java NIO中的Buffer 详解
Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...
- java NIO中的buffer和channel
缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...
- Java NIO中的Buffer类
Buffer 缓冲,用于批量读写数据 Buffer是一个抽象类,基本数据类型都有实现类:XxxBuffer,比如ByteBuffer.CharBuffer.IntBuffer.DoubleBu ...
- Java NIO中的缓冲区Buffer(一)缓冲区基础
什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...
- Java I/O(3):NIO中的Buffer
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 之前在调用Channel的代码中,使用了一个名叫ByteBuffer类,它是Buffer的子类.这个叫Buffer的类是专门用来解决高速设备与低 ...
- Java NIO中核心组成和IO区别
1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...
- Java NIO Channel和Buffer
Java NIO Channel和Buffer @author ixenos Channel和Buffer的关系 1.NIO速度的提高来自于所使用的结构更接近于OS执行I/O的方式:通道和缓冲器: 2 ...
- 转载Java NIO中的Files类的使用
Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法. Files.exists() Files.exits()方法用来检查给定的Path在文件 ...
- Java NIO中的缓冲区Buffer(二)创建/复制缓冲区
创建缓冲区的方式 主要有以下两种方式创建缓冲区: 1.调用allocate方法 2.调用wrap方法 我们将以charBuffer为例,阐述各个方法的含义: allocate方法创建缓冲区 调用all ...
随机推荐
- 20145234黄斐《java程序设计》第三周
教材学习内容总结 类与对象 定义:对象,与过程相对. Java中变量有2种类型,一个是基本类型,另一个则是类类型.基本类型在之前学过,本次学习类类型.使用Java撰写程序几乎都是在使用对象,要产生对象 ...
- [BZOJ4002][JLOI2015]有意义的字符串-[快速乘法+矩阵乘法]
Description 传送门 Solution 由于这里带了小数,直接计算显然会爆掉,我们要想办法去掉小数. 而由于原题给了暗示:b2<=d<=(b+1)2,我们猜测可以利用$(\fra ...
- iOS 中架构模式的浅显理解
我们开发软件中应用各种模式,主要是为了 职责划分:一个类只做一件事 易用,可维护,方便扩展 解耦,相互独立,可单独测试 各种设计模式其实都是在解决上面的问题,让我们对比看看吧. 一.如何理解MVC设计 ...
- Session丢失——解决方案
先抄下别人的作业(原帖:http://www.cnblogs.com/zhc088/archive/2011/07/24/2115497.html) Session丢失已经是一种习以为常的问题了,在自 ...
- Java EE JavaBean组件
一.简介 JavaBean组件是一些可移植.可重用并可组装到应用程序中的Java类,类必须是具体的和公共的. 符合下列设计规则的任何Java类均是以JavaBean: 1.对数据类型“protype” ...
- http-equiv=mobile-agent说明
Meta声明的格式:<meta http-equiv=”mobile-agent” content=”format=[wml|xhtml|html5]; url=url”> 比如: < ...
- 《图解 HTTP 》阅读 —— 第二章
第2章 简单的http协议 http 协议用于客户端和服务器端的通信. 请求访问文本或图像等资源的一端称为客户端,提供资源响应的一端称为服务器端. 请求报文: 响应报文: 为了能够处理大量的事务,ht ...
- centos 7 install gnome etc
centos yum 有grouplist子命令,可以查看当前系统有多少软件组件,里面就有gnome:"GNOME Desktop" sudo yum groupinstall G ...
- 【Python进阶】用 Python 统计字数
问题描述: 用 Python 实现函数 count_words(),该函数输入字符串 s 和数字 n,返回 s 中 n 个出现频率最高的单词.返回值是一个元组列表,包含出现次数最高的 n 个单词及其次 ...
- 我是IT小小鸟读书笔记
阅读了我是IT小小鸟后发现,自己开发程序是真的很苦难的,在现在这个空对空的时期,我们学习到大部分的全都是理论知识,而没有真正的去进行实践.没有经过实践,我们在程序开发过程中也就无法发现自身的困难. 在 ...