NIO提供了多种方法来创建一个与给定缓冲区共享内容的新缓冲区,这些方法对元素的处理过程各有不同。基本上,这种新缓冲区有自己独立的状态变量(position,limit,capacity和mark),但与原始缓冲区共享了同一个后援存储空间。任何对新缓冲区内容的修改都将反映到原始缓冲区上。可以将新缓冲区看作是从另一个角度对同一数据的透视。表5.4列出了相关的方法。

duplicate()方法用于创建一个与原始缓冲区共享内容的新缓冲区。新缓冲区的position,limit,mark和capacity都初始化为原始缓冲区的索引值,然而,它们的这些值是相互独立的。

表 5.4:在Buffer上创建不同透视的方法

方法

Capacity

新缓冲区的初始值

Position

Limit

Mark

ByteBuffer duplicate()

capacity

position

limit

mark

ByteBuffer slice()

remaining()

0

remaining()

未定义

ByteBuffer asReadOnlyBuffer()

capacity

position

limit

mark

CharBuffer asCharBuffer()

remaining()/2

0

remaining()/2

未定义

DoubleBuffer asDoubleBuffer()

remaining()/8

0

remaining()/8

未定义

FloatBuffer asFloatBuffer()

remaining()/4

0

remaining()/4

未定义

IntBuffer asIntBuffer()

remaining()/4

0

remaining()/4

未定义

LongBuffer asLongBuffer()

remaining()/8

0

remaining()/8

未定义

ShortBuffer asShortBuffer()

remaining()/2

0

remaining()/2

未定义

由于共享了内容,对原始缓冲区或任何复本所做的改变在所有复本上都可见。下面回到前面的例子,假设要将在网络上发送的所有数据都写进日志。


// Start with buffer ready for writing
ByteBuffer logBuffer = buffer.duplicate();
while (buffer.hasRemaining()) // Write all data to network
networkChannel.write(buffer);
while (logBuffer.hasRemaining()) // Write all data to logger
loggerChannel.write(buffer);

注意,使用了缓冲区复制操作,向网络写数据和写日志就可以在不同的线程中并行进行。

slice()方法用于创建一个共享了原始缓冲区子序列的新缓冲区。新缓冲区的position值是0,而其limit和capacity的值都等于原始缓冲区的limit和position的差值。slice()方法将新缓冲区数组的offset值设置为原始缓冲区的position值,然而,在新缓冲区上调用array()方法还是会返回整个数组。

Channel在读写数据时只以ByteBuffer为参数,然而我们可能还对使用其他基本类型的数据进行通信感兴趣。ByteBuffer能够创建一种独立的"视图缓冲区(view buffer)",用于将ByteBuffer的内容解释成其他基本类型(如CharBuffer)。这样就可以从该缓冲区中读取(写入数据是可选操作)新类型的数据。新缓冲区与原始缓冲区共享了同一个后援存储空间,因此,在任一缓冲区上的修改在新缓冲区和原始缓冲区上都可以看到。新创建的视图缓冲区的position值为0,其内容从原始缓冲区的position所指位置开始。这与slice()操作非常相似。不过,由于视图缓冲区操作的是多字节元素,新缓冲区的capacity和limit的值等于剩余总字节数除以每个该类型元素对应的字节数(例如,创建DoubleBuffer时则除以8)。

下面来看一个例子。假设通过某个Channel接收到一条消息,该消息由一个单独字节,后跟大量big-endian顺序的双字节整数(如short型)组成。由于该消息是通过Channel送达的,它一定在一个ByteBuffer中,在此为buf。消息的***个字节包含了消息中双字节整数的数量。你可能要调用***个字节指定次数的buf.getShort()方法,或者你可以一次获取所有的整数,如下所示:

// ...get message by calling channel.read(buf) ...
int numShorts = (int)buf.get();
if (numShorts < 0) {
throw new SomeException()
} else {
short[] shortArray = new short[numShorts];
ShortBuffer sbuf = buf.asShortBuffer();
sbuf.get(shortArray); // note: will throw if header was incorrect!
}

asReadOnlyBuffer()方法的功能与duplicate()方法相似,只是任何会修改新缓冲区内容的方法都将抛出ReadOnlyBufferException异常。包括各种型式的put(),compact()等,甚至连在缓冲区上调用无方向性的array()和arrayOffset()方法也会抛出这个异常。当然,对产生这个只读缓冲区的非只读缓冲区进行的任何修改,仍然会与新的只读缓冲区共享。就像用duplicate()创建的缓冲区一样,只读缓冲区也有独立的缓冲区状态变量。可以使用isReadOnly()方法来检查一个缓冲区是否是只读的。如果原缓冲区已经是只读的,调用duplicate()或slice()方法也将创建新的只读缓冲区。

Buffer透视:duplicate(),slice()等相关推荐

  1. netty io.netty.buffer简介

    2019独角兽企业重金招聘Python工程师标准>>> io.netty.util.ReferenceCounted 此接口代表一个引用计数的对象,此对象需要显示的释放. 当一个Re ...

  2. Buffer(缓冲/字节容器)详解

    本文来说下Buffer(缓冲/字节容器)详解 文章目录 概述 Buffer API ByteBuf - Netty 字节数据的容器 ByteBuf如何工作 ByteBuf 使用模式 HEAP BUFF ...

  3. [转]nodejs深入学(7)理解Buffer

    原文: https://www.jianshu.com/p/e3f14cdf78f1 --------------------------------------------------------- ...

  4. 【Nodejs】448- 深入学习 Node.js Buffer

    预备知识 ArrayBuffer ArrayBuffer 对象用来表示通用的.固定长度的原始二进制数据缓冲区.ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来 ...

  5. 【Netty】ByteBuf--Netty的数据容器

    ByteBuf–Netty的数据容器 网络传输的基本单位是字节,在Java NIO中,JDK提供了Buffer接口,以及其相关的实现作为NIO操作 数据的容器,如ByteBuffer等等. 而Nett ...

  6. Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍

    ## Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向 ...

  7. netty系列之:netty中的ByteBuf详解

    文章目录 简介 ByteBuf详解 创建一个Buff 随机访问Buff 序列读写 搜索 其他衍生buffer方法 和现有JDK类型的转换 总结 简介 netty中用于进行信息承载和交流的类叫做Byte ...

  8. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  9. Netty之有效规避内存泄漏

    有过痛苦的经历,特别能写出深刻的文章 -- 凯尔文. 肖 直接内存是IO框架的绝配,但直接内存的分配销毁不易,所以使用内存池能大幅提高性能,也告别了频繁的GC.但,要重新培养被Java的自动垃圾回收惯 ...

最新文章

  1. 华为笔记本怎么激活windows_取代Windows?最美国产操作系统诞生,华为笔记本电脑已搭载...
  2. cmake的使用-if-else的逻辑流程详解
  3. Excel导入MS SQL SERVER 操作
  4. 1.1为什么选择序列模型
  5. 最近谷歌苹果亚马逊扎堆收购的公司,会不会下一个就是你?
  6. mysql表损坏自动修复工具_对MySQL数据表(已损坏)的修复
  7. Koa2 和 Express 中间件对比
  8. idea 关闭检查更新_intellij idea怎么关闭自动更新
  9. Jmeter 线程数、Ramp-Up、循环次数 详解
  10. Arcgis进行人口密度计算
  11. unite_Unite 2016主题总结:有关图形,平台,VR等的新闻
  12. 代码设置margintop_js获取css属性,更改margin-top属性,给每个a标签的margin-top属性在原基础上 +5px...
  13. html5页面上下翻页特效,h5实现垂直上下翻页效果
  14. 二、小兔仙Vue3(项目介绍)
  15. 又一次回归,再一次记录
  16. 视频|《8问》浙江大学张宏鑫:边缘计算或许是区块链的福音
  17. c语言建立26个字母的顺序表,线性表的操作建立一个含26个英文字母的数据元素的线性表并输出该表 爱问知识人...
  18. asp.net毕业生信息管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
  19. 想随时定位自己做的智能设备在哪?安排,ESP32 + HaaS Python足矣,定位还能显示在地图上哦
  20. mac备忘录html,在 Mac 上撰写和格式化备忘录-添加提醒-添加日历

热门文章

  1. Notepad++的第三方插件介绍中文翻译
  2. HART475艾默生手操器维修注意事项及指标特点
  3. 关于ARMv8另外几个问题
  4. Taichi 加速 Python 中图像处理
  5. 滴滴出行用户运营分析
  6. 纯html+css打造一款特殊的生日贺卡
  7. 将计算机移动到桌面,如何将图标移动到桌面 移动桌面图标的方法分享
  8. Android逆向之旅—Hook神器Cydia Substrate使用详解
  9. 如何用MD5加密数据库的敏感数据?
  10. java currency 默认_Java Currency getDefaultFractionDigits()方法与示例