转载自:李会军•宁静致远
在第一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如果我们使用get()方法从缓冲区获取数据或者使用put()方法把数据写入缓冲区,都会引起缓冲区状态的变化。本文为NIO使用及原理分析的第二篇,将会分析NIO中的Buffer对象。
在缓冲区中,最重要的属性有下面三个,它们一起合作完成对缓冲区内部状态的变化跟踪:
position:指定了下一个将要被写入或者读取的元素索引,它的值由get()/put()方法自动更新,在新创建一个Buffer对象时,position被初始化为0。
limit:指定还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。
capacity:指定了可以存储在缓冲区中的最大数据容量,实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量。
以上四个属性值之间有一些相对大小的关系:0 <= position <= limit <= capacity。如果我们创建一个新的容量大小为10的ByteBuffer对象,在初始化的时候,position设置为0,limit和 capacity被设置为10,在以后使用ByteBuffer对象过程中,capacity的值不会再发生变化,而其它两个个将会随着使用而变化。四个属性值分别如图所示:
现在我们可以从通道中读取一些数据到缓冲区中,注意从通道读取数据,相当于往缓冲区中写入数据。如果读取4个自己的数据,则此时position的值为4,即下一个将要被写入的字节索引为4,而limit仍然是10,如下图所示:
下一步把读取的数据写入到输出通道中,相当于从缓冲区中读取数据,在此之前,必须调用flip()方法,该方法将会完成两件事情:
1. 把limit设置为当前的position值
2. 把position设置为0
由于position被设置为0,所以可以保证在下一步输出时读取到的是缓冲区中的第一个字节,而limit被设置为当前的position,可以保证读取的数据正好是之前写入到缓冲区中的数据,如下图所示:
现在调用get()方法从缓冲区中读取数据写入到输出通道,这会导致position的增加而limit保持不变,但position不会超过limit的值,所以在读取我们之前写入到缓冲区中的4个自己之后,position和limit的值都为4,如下图所示:
在从缓冲区中读取数据完毕后,limit的值仍然保持在我们调用flip()方法时的值,调用clear()方法能够把所有的状态变化设置为初始化时的值,如下图所示:
最后我们用一段代码来验证这个过程,如下所示:
import java.io.*; import java.nio.*; import java.nio.channels.*; public class Program { public static void main(String args[]) throws Exception { FileInputStream fin = new FileInputStream("d:\\test.txt"); FileChannel fc = fin.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(10); output("初始化", buffer); fc.read(buffer); output("调用read()", buffer); buffer.flip(); output("调用flip()", buffer); while (buffer.remaining() > 0) { byte b = buffer.get(); // System.out.print(((char)b)); } output("调用get()", buffer); buffer.clear(); output("调用clear()", buffer); fin.close(); } public static void output(String step, Buffer buffer) { System.out.println(step + " : "); System.out.print("capacity: " + buffer.capacity() + ", "); System.out.print("position: " + buffer.position() + ", "); System.out.println("limit: " + buffer.limit()); System.out.println(); } }
完成的输出结果为:
这与我们上面演示的过程一致。在后面的文章中,我们继续介绍NIO中关于缓冲区一些更高级的使用。
(未完待续)
相关推荐
java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较
Java NIO原理 图文分析及代码实现
NULL 博文链接:https://dengqsintyt.iteye.com/blog/2083316
NULL 博文链接:https://goon.iteye.com/blog/1775421
本文主要介绍Java NIO原理的知识,这里整理了详细资料及简单示例代码和原理图,有需要的小伙伴可以参考下
本文将主要分析Netty实现方面的东西,由于精力有限,本人并没有对其源码...对于Netty使用者来说,Netty提供了几个典型的example,并有详尽的API doc和guide doc,本文的一些内容及图示也来自于Netty的文档,特此致谢。
JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的、面向块的 I/O。本实用教程从高级概念到底层的编程细节,非常详细地介绍了 NIO 库。您将学到诸如缓冲区和通道这样的关键 I/O 元素的知识,并...
【图解】深入分析Java I_O工作机制,从传统IO分析至NIO,调优以及原理,不可用于商业用途,如有版权问题,请联系删除!
Nginx Location ReWrite 等语法配置及原理分析 Nginx提供https服务 基于Nginx+lua完成访问流量实时上报Kafka的实战 Netty 高性能NIO框架 IO 的基本概念、NIO、AIO、BIO深入分析 NIO的核心设计思想 Netty产生...
主要介绍了Java NIO Selector用法,结合实例形式分析了Java NIO Selector基本功能、原理与使用方法,并结合了多人聊天室实例加以详细说明,需要的朋友可以参考下
面试题包含了不同技术层面的面试问题,同时也能对一些没有面试开发经验的小白给予不可估量的包装, 让你的薪水绝对翻倍, 本人亲试有效.Java面试题84集、java面试专属及面试必问课程,所有的面试题有视屏讲解, 解答方案....
core-niojava nio 客户端和服务端交互实现主要通过长连接的方式进行数据交换,采用多路复用技术,同步非阻塞模式。主要有以下几个概念Channel(渠道,类似于高速公路可以处理很多线程io);Selector(选择器,可以...
Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
1.2 Java的竞争对手及各自优势 4 1.2.1 C#简介和优势 4 1.2.2 Ruby简介和优势 4 1.2.3 Python的简介和优势 5 1.3 Java程序运行机制 5 1.3.1 高级语言的运行机制 6 1.3.2 Java程序的运行机制和JVM 6 1.4 开发...
《Netty 权威指南(第2 版)》适合架构师、设计师、软件开发工程师、测试人员以及其他对JavaNIO 框架、Netty 感兴趣的相关人士阅读,通过《Netty 权威指南(第2 版)》的学习,读者不仅能够掌握Netty 基础功能的使用...
《Netty 权威指南(第2 版)》适合架构师、设计师、软件开发工程师、测试人员以及其他对JavaNIO 框架、Netty 感兴趣的相关人士阅读,通过《Netty 权威指南(第2 版)》的学习,读者不仅能够掌握Netty 基础功能的使用...
8.高性能网络编程必备技能之IO与NIO阻塞分析 10.微服务架构之Spring Cloud Eureka 场景分析与实战 11.高性能必学之Mysql主从架构实践 13.RPC底层通讯原理之Netty线程模型源码分析 14.分库分表之后分布式下如何保证ID...
47_Netty服务器与客户端编码模式回顾及源码分析准备 48_Netty与NIO系统总结及NIO与Netty之间的关联关系分析 49_零拷贝深入剖析及用户空间与内核空间切换方式 50_零拷贝实例深度剖析 51_NIO零拷贝彻底分析与Gather...