Java NIO 之 Buffer
Java NIO 之 Buffer
Java NIO (Non Blocking IO 或者 New IO)是一种非阻塞IO的实现。NIO通过Channel、Buffer、Selector几个组件的协同实现提升IO效率的目的。而ByteBuffer是其中最基础的一种Buffer实现。
阻塞 or 非阻塞
阻塞/非阻塞,同步/异步是两组非常容易产生混淆的概念。
同步/异步:是从消息通信机制的划分,如果调用者在没有得到结果前“调用”不返回,则是同步的。而如果调用发出后,调用直接返回,结果由被调用者通过某种机制(通知、状态)返回,则是异步的。
阻塞/非阻塞:是站在调用者的角度,描述调用者在等待调用结果时的状态。阻塞是指,在得到返回结果前,当前线程会被一直挂起,只有在得到结果后才返回。非阻塞是指,调用不会阻塞当前线程,可能不会得到想要的结果,但会立刻返回。
以找老板签报销单为例:
如果去老板工位发现老板不在,你一直站在旁边等老板回来签字才回去,那你就是阻塞的(好蠢。。。);
如果去老板工位发现老板不在,你立马回来继续撸代码,过会又跑去看看老板在不在,如果不在又回来喝口水。。。那这个过程你就是非阻塞的(也有点蠢。。。);
而上述两个过程中,“通信机制”都是同步的。而:
如果,你跑过去找老板签字,老板说放这吧,过会老板把签好的报销单交给你,那这次交互过程就是异步的(想得美。。。);
可见JAVA NIO是非阻塞式的IO,是同步的IO机制。
Buffer的结构
Buffer通过position,limit,capacity三个变量管理内容。其中:capacity标记Buffer总容量大小;position标识当前可读或者可写的初始位置;limit标记当前可读或者可写的极限位置,当Buffer处于write模式时,limit=capacity,当切换至Read模式时,limit为对应写模式时的position。三者满足:position <= limit <= capacity;一种Buffer从写模式切换至读模式的示意如下图:

Flip,Clear与Rewind
Clear操作,置position=0, limit=capacity,将Buffer置于写模式;
Flip操作,置limit=last_position, position=0,将Buffer置于读模式;
Rewind操作,置position=0, limit不变,使得可以重新读取Buffer中的内容。
HeapByteBuffer , Direct ByteBuffer 与 MappedByteBuffer
ByteBuffer本质是一块内存区域。对于ByteBuffer,可以通过allocate(int)和allocateDirect(int)分别分配Heap和Direct Buffer。ByteBuffer持有仅对Heap Buffer有效的一个字节型数组:
final byte[] hb; // Non-null only for heap buffers
可见HeapByteBuffer是直接分配在堆上的,可以简单理解为byte[]的一种封装。
而Direct Buffer不直接分配在堆上,其不受GC管理(而指向这块内存的Java对象是受GC管理的,只有GC回收了这个对象,操作系统才会释放Direct Buffer的内存空间)。
由于Direct Buffer由系统直接管理,其读写的消耗小于在堆上进行读写(减少了从系统至程序内存空间的拷贝)。实际上每次使用ByteBuffer进行读写时,都会临时开辟一段DirectBuffer(JDK实现上对其做了池化,避免了频繁创建和释放DirectBuffer带来的高系统调用消耗),将ByteBuffer中的内容拷贝进其中,再进行后续操作,多了一步Buffer间的拷贝操作。所以对于重复使用的Buffer,使用Direct Buffer的优点显而易见。
但是创建和释放Direct Buffer的代价则高于Heap Buffer(系统函数的直接调用),同时不当地使用DirectBuffer更容易引起内存泄漏。
MappedByteBuffer是一种DirectByteBuffer,而其内容是一个文件的全部或者部分映射。由于MappedByteBuffer对进行了文件进行了内存映射,避免了读写时进行write/read系统调用,所有在大文件读写方面具有极高的性能。但是其同样存在DirectByteBuffer存在的问题,同时涉及文件操作,文件的关闭也依赖于垃圾回收。
对上述三种Buffer进行测试对比,分别读写大小为1M,256M和1G的文件(过小的文件并没有性能上的明显差异),结果如下:



可见,当文件较小时三者并没有明显的性能差异。而在进行大文件的读写时MappedByteBuffer表现出了明显的性能优势。同时可以看到Direct和Heap之间并没有明显的差异。
Java NIO 之 Buffer的更多相关文章
- Java NIO之Buffer(缓冲区)
Java NIO中的缓存区(Buffer)用于和通道(Channel)进行交互.数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这 ...
- JAVA NIO简介-- Buffer、Channel、Charset 、直接缓冲区、分散和聚集、文件锁
IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. Java标准io回顾 在Java1.4之前的I/O系统中,提供 ...
- java nio之Buffer(一)
Buffer是一个包装了基本数据元素数组的对象,它以及它的子类定义了一系列API用于处理数据缓存. 一.属性 Buffer有四个基本属性: 1.capacity 容量,buffer能够容纳的最大元素 ...
- Java NIO -- 缓冲区(Buffer)的数据存取
缓冲区(Buffer): 一个用于特定基本数据类型的容器.由 java.nio 包定义的,所有缓冲区都是 Buffer 抽象类的子类.Java NIO 中的 Buffer 主要用于与 NIO 通道进行 ...
- Java NIO 之 Buffer(缓冲区)
一 Buffer(缓冲区)介绍 Java NIO Buffers用于和NIO Channel交互. 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels. Bu ...
- 【Java nio】buffer
package com.slp.nio; import org.junit.Test; import java.nio.ByteBuffer; /** * Created by sanglp on 2 ...
- java nio之Buffer
一.JAVA NIO 是在和channel交互的时候使用的.Channel将数据读入缓冲区,然后我们又从缓冲区访问数据.写数据时,首先将要发送的数据按顺序填入缓冲区.基本上,缓冲区只是一个列表,它的所 ...
- Java NIO:Buffer、Channel 和 Selector
Buffer 一个 Buffer 本质上是内存中的一块,我们可以将数据写入这块内存,之后从这块内存获取数据. java.nio 定义了以下几个 Buffer 的实现,这个图读者应该也在不少地方见过了吧 ...
- JAVA NIO缓冲区(Buffer)------ByteBuffer常用方法
参考:https://blog.csdn.net/xialong_927/article/details/81044759 缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对输入/输出(I ...
随机推荐
- 【Zookeeper】Zookeeper安装配置
本文演示使用三台Linux服务器安装Zookeeper,使用的是zookeeper-3.4.5版本,将zookeeper-3.4.5.tar.gz上传到linux服务器, 使用如下命令解压到/usr/ ...
- django 1.10.3 admin后台管理设置显示中文
在网上搜索的什么设置settings.py的LANGUAE_CODE,在1.10.3下完全不行,直接报错,后来使用了django.middleware.locale.LocaleMiddleware才 ...
- 运用C语言将图片转换成16进制的字符串(base64)
最近在写手机端的性能测试脚本的时候,发现手机在上传图片数据时,先将图片转换成一堆16进制的字符,将字符传输过去,服务器再将字符解码成图片 我们在loadrunner中测试时,就需要用C语言将图片编码. ...
- WebPack错误集
webpack-dev-server跨域设置反向代理出现404错误 问题栈 分析解决 看到404后,再次看了下启动服务配置文件,估计是pathRewrite这个没起作用; //代理服务器 const ...
- python对pywifi模块的认识
pywifi是一个用来搞wifi的模块 下一章我们将用他破解wifi密码 pywifi安装 pip install pywifi 下列代码判断是否有无限网卡 import pywifi import ...
- 51nod 1231 记分牌
链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1231 一个得分合法等价于前k小的得分之和大于等于$\frac{k* ...
- HDU-5421Victor and String
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5421 因为要在前面插字符,所以维护一个前缀链和后缀链,在同一棵回文树上搞,如果有某个最长回文后缀(或前缀) ...
- 《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)
上一篇我们讲解了DispatcherServlet的url-pattern配置详解,今天我们来真正对SpringMVC进行配置式开发.所谓配置式开发是指“处理器类是程序员自己定义的.实现了特定接口的类 ...
- Windows系统下文件的概念及c语言对其的基本操作(丙)
- Vue.js实现一个SPA登录页面的过程
技术栈 vue.js 主框架 vuex 状态管理 vue-router 路由管理 一般过程 在一般的登录过程中,一种前端方案是: 检查状态:进入页面时或者路由变化时检查是否有登录状态(保存在cooki ...