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 ...
随机推荐
- JDK源码 - ArrayList
/** * ArrayList源码分析 * @author liyong * */ public class Util { @SuppressWarnings("unchecked" ...
- vb代码之-------当窗体BorderStyle属性为0时,添加窗口预览到任务栏
入吾QQ群183435019 (学习 交流+唠嗑) 有很多时候,我们为了美观,将会自己画一个标题栏,这时候我们会把原来的标题栏取消掉,最简单的方法是吧窗体的BorderStyle设置成为0, 然后自己 ...
- 咫尺论坛|即速应用-微信小程序社区
咫尺论坛|即速应用-微信小程序社区 是一个集微信和支付宝小程序行业资讯.开发资源.技术交流于一身的大型小程序开发论坛,成立伊始便迅速聚集了一大批小程序开发爱好者,短时间内成为了国内领先的小程序开发者社 ...
- 应用服务器GC回收常见问题总结
近一段时间多次发现因GC问题造成系统性能问题(应用服务间歇性响应缓慢.应用服务器CPU占用较高等),在此总结一下: 1.代码中直接调用GC.Collect() 2.字符串等操作频繁的内存申请 3.频繁 ...
- Android基础_BroadcastReceiver
一:什么是BroadcastReceiver Broadcast(广播)是一种广泛运用于在应用程序之间一步传播消息的机制系统消息Android系统发出的,电池不足.来电信息等自定义消息第三方应用发出的 ...
- Java中的集合框架(下)
学生选课--判断Set中课程是否存在 package com.imooc.collection; import java.util.ArrayList; import java.util.Arrays ...
- Django普通文件上传
前端代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- HDU 3377 Plan
Problem Description One day, Resty comes to an incredible world to seek Eve -- The origin of life. L ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)(A.思维题,B.思维题)
A. Vicious Keyboard time limit per test:2 seconds memory limit per test:256 megabytes input:standard ...
- HDU--1164
Eddy's research I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...