图解java中的bytebuffer
因何而写
网上关于bytebuffer的文章真的很多,为何在此还要写一篇呢?主要是基于以下几点考虑
用极易的方式认识一下bytebuffer
bytebuffer之第一眼印象
我们可以把bytebuffer理解成如下几个成员组成的一个新对象,对,就是一个普通的java对象,像string一样的java对象。(强调一下,这里只是说这样理解,实际上有些bytebuffer的实现类并非这样实现,并且这里只列出掌握bytebuffer所需要的最小知识集合,其它诸如mark等字段本文并不介绍,以免增加初学者的惑度)
- byte[] bytes: 用来存储数据
- int capacity: 用来表示bytes的容量,那么可以想像capacity就等于bytes.size(),此值在初始化bytes后,是不可变的。
- int limit: 用来表示bytes实际装了多少数据,可以容易想像得到limit <= capacity,此值是可灵活变动的
- int position: 用来表示在哪个位置开始往bytes写数据或是读数据,此值是可灵活变动的
通过下图,对bytebuffer形成一个感观认识吧
bytebuffer之常用操作及各操作对内部变量带来的变化
创建bytebuffer: ByteBuffer.allocate(6)
写入一个字节: byteBuffer.put((byte)3)
读取一个字节: byte bs = byteBuffer.get()
对于刚刚写好的bytebuffer,我们要读取它的内容,需要先设置一下position和limit,否则读的位置就不对
byteBuffer.position(0); //设置position到0位置,这样读数据时就从这个位置开始读
byteBuffer.limit(1); //设置limit为1,表示当前bytebuffer的有效数据长度是1
我们看一下,设置position和limit后,bytebuffer的内部变化
接下来,我们就可以读取刚才写入的数据了
byte bs = byteBuffer.get();
bytebuffer之使用心得
这里说的是作者本人使用bytebuffer的一些心得,这些与其说是心得,不如说是实践+测试得来的一些经验,所以并不保证就是权威的,欢迎有更深研究的朋友来合理讨论,如果有不同意见,可以以更好的论据来说服对方。
HeapByteBuffer.get(byte[], int, int)效率不如 System.arraycopy()
前者实现的原理是用for循环来做的,后者是内存复制,t-io一般是用后者来做bytebuffer的组合,譬如SendRunnable.java的下面这段代码
ByteBuffer allByteBuffer = ByteBuffer.allocate(allBytebufferCapacity);
byte[] dest = allByteBuffer.array();
for (ByteBuffer byteBuffer : byteBuffers) {
if (byteBuffer != null) {
int length = byteBuffer.limit();
int position = allByteBuffer.position();
System.arraycopy(byteBuffer.array(), 0, dest, position, length);
allByteBuffer.position(position + length);
}
}
注意:如果DirectBuffer并不能用System.arraycopy来代替get(byte[], int, int),因为这货的内部实现不是byte[]的
jdk自带的bytebuffer已经足够好用
有一些nio/aio框架喜欢自己弄一套bytebuffer来,既增加了作者自己的工作量,又增加了用户的学习成本,但我们要知道一点,nio/aio在发送数据时,最终的参数是jdk的bytebuffer,我们真的有必要再作一次转换和计算吗?尽管某些中间过程是“零拷贝”(这个“零拷贝”也是有额外的计算成本的)的,但是jdk版bytebuffer的诞生到发送完毕,这整个过程经历了哪些操作呢?真的是如某书某博客上所说的“零拷贝”吗?更不应该把某些对象池的做法也牵强附会到“零拷贝”的概念中来----对象池属对象重复利用范畴,既然是重复利用自然便已经默认有零拷贝的属性了,但是对象池本身的维护也是需要消耗资源的,所以并不是所有场景说用了对象池,性能就提升了,有时候用不好反而增加负担,所以万事要以测试数据为准,不应盲目人云亦云!
最后附上bytebuffer的示例程序
这里附上bytebuffer的示例程序,用户可以自己debug观察观察,增加bytebuffer的相关概念,以便更灵活的运用bytebuffer
import java.nio.ByteBuffer; /**
* @author tanyaowu
* 2017年5月1日 上午9:00:50
*/
public class Ts { /**
*
* @author: tanyaowu
*/
public Ts() {
} /**
* @param args
* @author: tanyaowu
*/
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
byteBuffer.put((byte)3); byteBuffer.position(0); //设置position到0位置,这样读数据时就从这个位置开始读
byteBuffer.limit(1); //设置limit为1,表示当前bytebuffer的有效数据长度是1 byte bs = byteBuffer.get();
System.out.println(byteBuffer);
}
}
图解java中的bytebuffer的更多相关文章
- 一、图解Java中String不可变性
这里有一堆例子来说明Java的String的不可变性. 1.声明一个String String s = "abcd"; s 变量保存string对象的引用,下面的箭头解释成保存了哪 ...
- Java中this、static关键字的内存图解
Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break dou ...
- Java中数组在内存中的图解
Java中的数组在内存中的图解,其实对于数组,还是比较熟悉的,平时用的也是很多的,在看数据结构与算法的极客时间专栏,最常用的10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie ...
- (转载)图解Java多态内存分配以及多态中成员方法的特点
图解Java多态内存分配以及多态中成员方法的特点 图解Java多态内存分配以及多态中成员方法的特点 Person worker = new Worker(); 子类实例对象地址赋值给父类类型引 ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- 关于Java中基本类型的长度相关基础知识
1. 用HeapByteBuffer放int占几个byte? 占4个.而且不论你是放1还是-1还是0xffff. 因为int的长度是4个byte,HeapByteBuffer的存储又是byte数组. ...
- java中常用的工具类(一)
我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...
- 深入分析 Java 中的中文编码问题
登录 (或注册) 中文 IBM 技术主题 软件下载 社区 技术讲座 打印本页面 用电子邮件发送本页面 新浪微博 人人网 腾讯微博 搜狐微博 网易微博 Digg Facebook Twitter Del ...
- [转]深入分析 Java 中的中文编码问题
收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编 ...
随机推荐
- 如何检测被锁住的Oracle存储过程
今天遇到了这个情况,然后在网上找了到了这篇文章,借鉴过来做参考吧! 1.查看是哪一个存储过程被锁住 查V$DB_OBJECT_CACHE视图 select * from V$DB_OBJECT_CAC ...
- 简单的Java逻辑小代码(打擂台,冒泡排序,水仙花数,回文数,递归)
1.打擂台 简单的小代码,打擂台.纪念下过去,祝福下新人. public static void main(String[] args){ int[] ld = {1,4,2,10,8,9,5}; i ...
- Mac环境svn的使用
在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...
- java并发编程——通过ReentrantLock,Condition实现银行存取款
java.util.concurrent.locks包为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器.该框架允许更灵活地使用锁和条件,但以更难用的语法为代价. Lock 接口 ...
- Day6_内置函数
定义完一个有名函数,可以直接利用函数名+括号来执行,例如:func() 有名函数: def func(x,y,z=1): return x+y+z 匿名函数: lambda x,y,z=1:x+y+z ...
- 兼容 Android 4.4 透明状态栏与导航栏
http://www.apkbus.com/Android-163388-1-1.html?_dsign=73d41229 android 系统自4.2 开始 UI 上就没多大改变,4.4 也只是增加 ...
- Artwork
A template for an artwork is a white grid of n × m squares. The artwork will be created by painting ...
- R贡献文件中文
贡献文件 注意: 贡献文件的CRAN区域被冻结,不再被主动维护. 英文 --- 其他语言 手册,教程等由R用户提供.R核心团队对内容不承担任何责任,但我们非常感谢您的努力,并鼓励大家为此列表做出贡献! ...
- ns3构建2 core fat tree出错
我用ns3构建fat tree以下是我的拓扑结构: 在我用ns3构建完这个拓扑结构,并且加上此行代码: 但是运行的时候报错了.报的错误是: 解决办法是:进入到/src/internet/model/g ...
- JavaScript高级程序设计(一)
一.三种常见的著名的命名规则: 1.Camel(驼峰式命名):首字母是小写的,接下来的单词都以大写字母开头.例如:var myTestValue=0; 2.Pascal(帕斯卡命名):首字母是大写的 ...