1、Buffer的工作方式
  前面《java NIO的工作方式》介绍了Selector检测到通信信道I/O有数据传输时,通过select()方法取得SocketChannel,将数据读取或写入Buffer缓冲区,下面讨论Buffer如何接受和写出数据。通过查看JDK源码可知道,Buffer的构造函数

 Buffer(int mark, int pos, int lim, int cap) {    // package-privateif (cap < 0)throw new IllegalArgumentException();this.capacity = cap;limit(lim);position(pos);if (mark >= 0) {if (mark > pos)throw new IllegalArgumentException();this.mark = mark;}}

  Buffer可以简单的理解为一组基本数据类型的元素列表,它通过几个变量来保存这个数据的当前位置状态,也就是四个索引

    private int mark = -1;private int position = 0;private int limit;private int capacity;

表1-1 Buffer中的索引及说明

在实际操作数据时他们关系如图1-2所示。

我们通过ByteBuffer.allocate(11)方法创建一个11个byte的数组缓冲区,初始状态如图1-2所示,position的位置为0,capacity和limit默认都是数组长度。当我们写入5个字节时位置变化如图1-3所示。

注意:我们查看ByteBuffer.allocate()方法源码可知,执行的是以下代码

ByteBuffer(int mark, int pos, int lim, int cap, // package-privatebyte[] hb, int offset){super(mark, pos, lim, cap);this.hb = hb;this.offset = offset;}public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();return new HeapByteBuffer(capacity, capacity);}

返回的是HeapByteBuffer又是ByteBuffer的子类,并且在HeapByteBuffer的构造方法中执行的是这样一个语句:

super(-1, 0, lim, cap, new byte[cap], 0);

也就是说调用的还是ByteBuffer中的构造方法,包范围内使用。这个方法做了如下工作,首先调用Buffer的构 造方法,依次初始化mark、position、limit、capacity,然后初始化ByteBuffer的属性byte数组,接着初始 offset,这样使用allocate方法就可以构造出一个ByteBuffer对象了。

这时我们需要将缓冲区的5个字节数据写入Channel通信信道,所以我们调用byteBuffer.flip()方法,查看源码得知

 public final Buffer flip() {limit = position;position = 0;mark = -1;return this;}

limit走到position的位置,而position回到了初始位置0,倒转了缓冲区,数组的状态发生如图1-4所示的变化。

这时底层操作系统就可以从缓冲区中正确读取这5个字节数据并发送出去了。在下一次写数据之前我们在调一下clear()方法,缓冲区的索引状态又回到初始位置。

public final Buffer clear() {position = 0;limit = capacity;mark = -1;return this;}

  这里还要说明一下mark,当我们调用mark()方法时,它将记录当前position的前一个位置,当我们调用reset时,position将恢复mark记录下来的值。还有一点需要说明,通过Channel获取I/O数据首先要经过操作系统的Socket缓冲区再将数据复制到Buffer中,这个操作系统缓冲区就是底层的TCP协议关联的RecvQ或SendQ队列,从操作系统缓冲区到用户缓冲区复制数据比较耗性能,Buffer提供了另外一种直接操作操作系统缓冲区的方式,即ByteBuffer.allocateDirector(size),

 public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);}

这个方法返回的DirectorByteBuffer就是与底层存储空间关联的缓冲区,它通过Native代码操作非JVM堆的内存空间。每次创建或者释放的时候都调用一次System.gc()。注意,在使用DirectorByteBuffer时可能会引起JVM内存泄露问题。DirectByteBuffer和Non-Direct Buffer(HeapByteBuffer)对比如图1-5所示。

转载于:https://www.cnblogs.com/wcyBlog/p/4719352.html

Buffer的工作方式相关推荐

  1. 并行接口电路8255A的基本使用——三种工作方式的时序图的具体讲解

    文章目录 概述 内部结构图和具体引脚功能 端口A 端口B![在这里插入图片描述](https://img-blog.csdnimg.cn/20210607164952661.png) 端口C 与处理器 ...

  2. ZYNQ 7000 USB HS启动流程和工作方式

    目录 1.USB数据结构 2.USB设备启动流程和工作方式 (1).通过ID查找USB配置信息UsbConfigPtr (2).将USB配置信息UsbConfigPtr挂接到XUsbPS对象实例Usb ...

  3. TLB 结构和工作方式

    TLB: TLB 即 Translation Lookaside Buffer ,根据功能可以译为快表,直译可以翻译为旁路转换缓冲,也可以把它理解成页表缓冲. 其中每一行都保存着一个由单个PTE(Pa ...

  4. LVS原理详解(3种工作方式8种调度算法)--老男孩

    一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...

  5. 30岁找不到工作很绝望_计算机为绝望的新编码员工作方式的快速指南

    30岁找不到工作很绝望 by Danielle Ormshaw 丹妮尔·欧姆肖(Danielle Ormshaw) 计算机为绝望的新编码员工作方式的快速指南 (The quick guide to t ...

  6. 超越Android:Kotlin在后端的工作方式

    by Adam Arold 亚当·阿罗德(Adam Arold) 超越Android:Kotlin在后端的工作方式 (Going Beyond Android: how Kotlin works on ...

  7. 开源许可证 如何工作_开源许可证的工作方式以及如何将其添加到您的项目中...

    开源许可证 如何工作 by Radu Raicea 由Radu Raicea 开源许可证的工作方式以及如何将其添加到您的项目中 (How open source licenses work and h ...

  8. 《编译与反编译技术实战》——2.1节编译器、解释器及其工作方式

    本节书摘来自华章社区<编译与反编译技术实战>一书中的第2章,第2.1节编译器.解释器及其工作方式,作者刘晓楠 陶红伟 岳 峰 戴超,更多章节内容可以访问云栖社区"华章社区&quo ...

  9. Makefile —— Makefile的规则是什么?make是如何工作的?make的工作方式是什么?

    #1.Makefile的规则: #   target... : prerequisites... #        command target是:[目标文件:包含执行文件edit与中间目标文件(*. ...

最新文章

  1. sql 相加_SQL-多表查询
  2. 布隆过滤器速度_布隆过滤器的分析和实现
  3. poj3687Labeling Balls
  4. redis 计数器 java_Redis 实践汇总和使用建议。
  5. 数据类型转换_注意事项
  6. Oracle之同义词,DBLINK,表空间
  7. Spring--@within和@target的区别
  8. linphone-android移植
  9. Android学习笔记(八)XML文档的解析
  10. java 树形菜单遍历_java实现遍历树形菜单方法——service层
  11. 快手诉“短视频人气助手”软件不正当竞争:索赔100万元
  12. Linux安全加固--系统相关
  13. OpenCV3 install tutorial for Mac
  14. 【QT】Qaction和触发函数建立连接的方法
  15. 如何以CustomValidator搭配jQuery AJAX进行Server端验证(转)
  16. mysql sqlyog 备份计划_SqlYog 自动备份数据库
  17. Oracle | oracle11g安装环境变量配置
  18. 500个爆文标题_爆文标题创作思路——来自100个10W+的标题的总结
  19. jqGrid设置三级表头和表头合并
  20. 嵌入式开发培训多长时间?嵌入式课程怎么学?

热门文章

  1. python计时器精度_在python中获得更精确的计时器
  2. Python 十六进制转Base64_马克的Python学习笔记#数据编码与处理 4
  3. php 动态分页,PHP动态分页函数,PHP开发分页必备啦
  4. oss生成唯一文件名_根据结构化自然语言规范自动生成精确预言
  5. python 列表推导式
  6. Linux终端C语言实现图片拷贝
  7. python检查_python设置检查点简单实现
  8. 设置最大值_电机变频器参数设置不当会怎样
  9. 直方图(opencv)
  10. POJ - 2337 Catenyms 欧拉回路