Java NIO (一)简介(备份)

1 NIO简介

        在1.4版本之前,Java NIO类库是阻塞IO,从1.4版本开始,引进了新的异步IO库,被称为Java New IO类库,简称为Java NIO。New IO类库的目的 就是要让Java支持非阻塞IO。

        Java NIO类库包含三个核心组件:

        1、Channel(通道)

        2、Buffer(缓冲区)

        3、Selector(选择器)

        理解了上一章高并发IO底层原理,大家会马上识别出来Java NIO属于第三种模型——IO多路复用模型。只不过,Java NIO组件提供了统一的API,为大家屏蔽了底层的操作系统的差异。

        本章,会对上面3个组件展开详细介绍。首先看一下Java NIO和OIO的简单对比。

1.1 NIO和OIO的对比

        在Java中,NIO和OIO的区别主要体现在三个地方:

        1、OIO是面向流的,NIO是面向缓冲区的。在一般的OIO操作中,面向字节流或字符流的IO操作总是以流式的方式顺序地从一个流(Stream)中读取一个或多个字节,因此,我们不能随意改变读取指针的位置。在NIO操作中则不同,NIO中引入了Channel和Buffer的概念。面向缓冲区的读取和写入只需要从通道读取数据到缓冲区中,或将数据从缓冲区写入到通道中。NIO不像OIO那样顺序操作,它可以随意读取Buffer中任意位置的数据。

        2、OIO的操作是阻塞的,而NIO是非阻塞的。OIO操作时,例如调用一个read方法读取一个文件的内容,调用read的线程就会被阻塞,直到read操作完成。在NIO模式中,当调用read方法时,如果此时有数据,则read读取数据并返回,如果此时没有数据,则read也返回直接返回,而不会阻塞当前线程。

        3、OIO没有选择器(Selector)的概念,而NIO有选择器的概念。NIO的实现是基于底层选择器的系统调用的,所以NIO需要底层操作系统提供支持,而OIO不需要选择器。

1.2 通道

        在OIO中,同一个网络连接会关联两个流:一个是输入流(Input Stream),另一个是输出流(Output Stream)。Java应用程序通过这两个流不断地进行输入和输出的操作。

        在NIO中,一个网络连接使用一个通道表示,所有NIO的IO操作都是通过连接通道完成的。一个通道类似于OIO中两个流的结合体,既可以从通道读取数据,也可以向通道写入数据。

1.3 选择器

        首先回顾一下前面介绍的基础知识——IO多路复用(高并发IO底层原理)指的是一个进程/线程可以同时监视多个文件描述符(含socket连接),一旦其中的一个或多个文件描述符可读或者可写,该监听进程/线程就能够进行IO就绪事件的查询。

        在Java应用层面,如何实现对多个文件描述符的监视呢?需要用到一个非常重要的Java NIO组件——选择器。选择器可以理解为一个IO事件的监听与查询器。通过选择器,一个线程可以查询多个通道的IO事件的就绪状态。

        从编程实现维度来说,IO多路复用变成的第一步是把通道注册到选择器中,第二步是通过选择器所提供的事件查询(select)方法来查询这些注册的通道是否有已经就绪的IO事件(例如可读、可写、网络连接完成等)。

        由于一个选择器只需要一个线程进行监控,因此我们可以很简单地使用一个线程,通过选择器去管理多个连接通道。

        与OIO相比,NIO使用选择器的最大优势就是系统开销小。系统不必为每一个网络连接(文件描述符)创建进程/线程,从而大大减少了系统的开销。总之,一个线程负责多个连接通道的IO处理是非常高效的,这种高效来自Java的选择器组件Selector及其底层的操作系统IO多路复用技术的支持。

1.4 缓冲区

        应用程序与通道的交互主要是进行数据的读取和写入。为了完成NIO的非阻塞读写操作,NIO准备了第三个重要的组件——Buffer。所谓通道的读取,就是将数据从通道读取到缓冲区中;通道的写入,就是将数据从缓冲区写入通道中。缓冲区的使用是面向流进行读写操作的OIO所没有的,也就是NIO非阻塞的重要前提和基础之一。

2 Buffer类

        Buffer类是一个抽象类,对应于Java的主要数据类型。在NIO中,有8种缓冲区类,分别是ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer。前7种Buffer类型覆盖了能在IO中传输的所有Java基本数据类型,第8种类型是一种专门用于内存映射的ByteBuffer类型。不同的Buffer子类可以操作的数据类型能够通过名称进行判断,比如IntBuffer只能操作Integer类型的对象。

        实际上,使用最多的是ByteBuffer(二进制字节缓冲区)类型,后面的章节会看到它的具体使用。

2.1 Buffer类的重要属性

        Buffer的子类会拥有一块内存,作为数据的读写缓冲区,但是读写缓冲区并没有定义在Buffer基类中,而是定义在具体的子类中。例如,ByteBuffer子类就拥有一个byte[]类型的数组成员

final byte[] hb; 

可以作为自己的读写缓冲区,数据的元素类型与Buffer子类的操作类型相对应。为了记录读写的状态和位置,Buffer类额外提供了一些重要的属性,其中有三个重要的成员属性:capacity(容量)、position(读写位置)和limit(读写的限制)。

        1、capacity属性

        Buffer类的capacity属性表示内存容量的大小。一旦写入的对象数量超过了capacity,缓冲区就满了,不能在写入。capacity属性一旦初始化,就不能再改变。原因是什么呢?Buffer类的对象在初始化时会按照capacity分配内部数组的内存,在数据内存分配好之后,它的大小就不能改变了。前面讲到,Buffer类是一个抽象类,Java不能直接用来创建对象。在具体使用的时候,必须使用Buffer的某个子类,例如DoubleBuffer子类,该子类能写入的数据类型是double,如果在创建实例时,其capacity是100,那么最多可以写入100个double类型的数据。

        【注意】capacity不是指内部的内存块byte[]数组的字节数量,而是指能写入的数据对象的最大限制数量。

        2、position属性

        position表示当前的位置。position属性的值与缓冲区的读写模式有关,在不同的模式下,position属性值的含义是不同的,在缓冲区进行读写的模式改变时,position值会进行相应的调整。

        在写模式下,position值的变化规则如下:

        (1)在刚进入写模式时,position值为0,表示当前的写入位置从头开始。

        (2)每当一个数据写到缓冲区后,position就会向后移动到下一个可写的位置。

        (3)初始的position值为0,最大可写值为limit-1。当position值达到limit时,缓冲区就已经无可用空间写入了。

        在读模式下,position值的变化规则如下:

        (1)当缓冲区刚开始进入读模式时,position会被重置为0.

        (2)当从缓冲区读取时,也是从position位置开始读。读取数据后,position向前移动到下一个可读的位置。

        (3)在读模式下,limit表示可读数据的上线。position的最大值为最大可读上线limit,当position达到limit时表示缓冲区已经无数据可读。

        Buffer的读写模式具体如何切换呢?当新建了一个缓冲区实例时,缓冲区处于写模式,这时可以写入数据。在数据写入完成后,如果要从缓冲区读取数据,就要进行模式的切换,可以调用flip()方法将缓冲区变成读模式,flip为翻转的意思。再从写模式到读模式的翻转过程中,position和limit属性值会进行调整,具体的规则是:

        (1)limit属性被设置成写模式时的position值,表示可以读取的最大数据位置。

        (2)position由原来的写入位置变成新的可读位置,也就是0,表示可以从头开始读。

        3、limit属性

        limit属性表示可以写入或读取的数据最大上限,其属性值的具体含义也与缓冲区的读写模式有关。在不同的模式下,limit值的含义是不同的,具体分为以下两种情况。

        (1)在写模式下,limit属性值的含义为可以写入的数据最大上限。在刚进入写模式时,limit的值会被设置成缓冲区的capacity值,表示可以一直将缓冲区的容量写满。

        (2)在读模式下,limit值的含义为最大能从缓冲区读取多少数据。

        一般来说,在进行缓冲区操作时是先写入再读取。当缓冲区写入完成后,就可以开始从Buffer读取数据,调用flip()方法,这时limit的值也会进行调整。具体如何调整呢?将写模式下的position值设置成读模式下的limit值,也就是说,将之前写入的最大数量作为可以读取数据的上限值。

        Buffer在翻转时的属性值调整主要涉及position,limit两个属性,但这种调整比较微妙,不太好理解,下面举例说明:

        首先,创建缓冲区。新创建的缓冲区处于写模式,其position值为0,limit值为最大容量capacity。

        然后,向缓冲区写数据。每写入一个数据,position向后面移动一个位置,也就是position的值加1。这里假定写入了5个数,当写入完成后,position的值为5.

        最后,使用flip()方法将缓冲区切换到读模式。limit的值会先被设置成写模式的position值,所以新的limit的值是5,表示可以读取数据的最大上限是5.之后调整position值,新的position会被重置为0,表示可以从0开始读。

        缓冲区切换到读模式后就可以从缓冲区读取数据了,一直到缓冲区的数据读取完毕。

        除了以上capacity、limit、position三个重要的成员属性外,Buffer还有一个比较重要的标记属性:mark(标记)属性。该属性的大致作用是:在缓冲区操作过程中,可以将当前的position值临时存入mark属性中,需要的时候,再从mark中取出暂存的标记值,恢复到position属性中,重新从position位置开始处理。

        下面用表总结一下Buffer类的四个重要属性。

508f47c9644b4ddcbb2f80038a3a60a5.jpeg

 

       

   

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Shell基本操作(2)

文件显示与编辑 连接并显示文件内容 cat cat[options] file... options -n加上行号 -s将连续两行以上的空白行替换为一行如果file不止一个文件,则会将它们连接起来如果想一次只看一页,可以使用more或者less命令 过滤文件内容grep grep命令可以查找拥…

【STM32CubeMX串口通信详解】USART1 -- DMA发送 + DMA空闲中断 接收不定长数据

文章目录: 前言 一、准备工作 1、接线 2、新建工程 二、CubeMX的配置 1、USART1 配置 异步通信 2、通信协议参数 3、打开DMA发送、接收 三、发送操作、代码解释 四、printf 重定向到USART1 五、接收代码的编写 1、定义一个结构体变量&a…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(4)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

金和OA jc6 Upload 任意文件上传漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助…

༺༽༾ཊ—设计-七个原则-模式—ཏ༿༼༻

第一原则:单一职责 一个类只负责一个功能领域中的相应职责; 接下来我们举一个代码例子,主要的功能实现是: 在主函数中运行调用描边工具和填充工具画矩形与圆形 首先写一个圆形类,里面只有一个方法用来返回string类型…

SAP中采购文档价格条件可以删除吗?

首先要声名,基于采购价格条件的严谨性和历史追朔需求,删除属于危险操作。不建议普通用户去执行操作。如果有兴趣,在测试系统中自行测试一下即可。正式系统中,还请慎重处理。 笔者公司日常不会去删除采购价格,日常处理…

Word2Vec的CBOW模型

Word2Vec中的CBOW(Continuous Bag of Words)模型是一种用于学习词向量的神经网络模型。CBOW的核心思想是根据上下文中的周围单词来预测目标单词。 例如,对于句子“The cat climbed up the tree”,如果窗口大小为5,那么…

微信小程序(四)页面跳转

注释很详细&#xff0c;直接上代码 新增内容 1.相对路径页面跳转 2. 绝对路径页面跳转 index.wxml <!-- navigator是块级元素&#xff0c;占一整行 --> <!-- 页面跳转url&#xff0c;相对路径 --> <navigator url"../logs/logs"><button type&…

赋值运算符和关系运算符

赋值运算符和关系运算符 赋值运算符 分类 符号作用说明赋值int a 10&#xff0c; 将10赋值给变量a加后赋值a b&#xff0c;将a b的值赋值给a-减后赋值a - b&#xff0c;将a - b的值赋值给a*乘后赋值a * b&#xff0c;将a b的值赋值给a/除后赋值a / b&#xff0c;将a b的…

运维知识点-Sqlite

Sqlite 引入 依赖 引入 依赖 <dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.36.0.3</version></dependency>import javafx.scene.control.Alert; import java.sql.*;public clas…

第二证券:抢占技术前沿 中国光伏企业结伴“走出去”

2024年新年前后&#xff0c;光伏职业分外忙碌。据证券时报记者不完全统计&#xff0c;晶澳科技、华晟新动力、高测股份、华民股份等多家企业宣告新建项目投产&#xff0c;安徽皇氏绿能等企业的项目也迎来设备安装的重要节点。 证券时报记者采访多家企业的负责人后了解到&#…

tessreact训练字库

tessreact主要用于字符识别&#xff0c;除了使用软件自带的中英文识别库&#xff0c;还可以使用Tesseract OCR训练属于自己的字库。 一、软件环境搭建 使用Tesseract OCR训练自己的字库&#xff0c;需要安装Tesseract OCR和jTessBoxEditor(配套训练工具)。jTessBoxEditor需要…

基于SSM的社区老年人关怀服务系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【23种设计模式应用场景汇总】

23种设计模式应用场景汇总 设计模式是一种在软件开发中解决特定问题的通用解决方案。下面我将尝试将23种设计模式融入到一个场景中&#xff1a; 假设我们正在开发一个在线购物系统&#xff0c;我们可以使用以下设计模式&#xff1a; 1. 工厂方法模式&#xff1a;当用户在网站上…

力扣hot100 只出现一次的数字 位运算

Problem: 136. 只出现一次的数字 文章目录 思路复杂度Code 思路 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public int singleNumber(int[] nums) {int res 0;for(int x : nums)res ^ x;return res;} }

UI自动化测试框架

文章目录 UI自动化基础什么是UI自动化测试框架UI自动化测试框架的模式数据驱动测试框架关键字驱动测试框架行为驱动测试框架 UI自动化测试框架的作用UI自动化测试框架的核心思想UI自动化测试框架的步骤UI自动化测试框架的构成UtilsLog.javaReadProperties.Java coreBaseTest.ja…

【分布式技术】监控技术zabbix实操

目录 一、脚本监控nginx的连接状态 步骤一&#xff1a;做好nginx的配置 步骤二&#xff1a;完成监控数据脚本编写&#xff0c;并使用zabbix_get测试 步骤三&#xff1a;在zabbix agent配置目录中&#xff0c;编写以conf结尾的用户参数文件 步骤四&#xff1a;在zabbix web…

Python 网络编程之TCP详细讲解

【一】传输层 【1】概念 传输层是OSI五层模型中的第四层&#xff0c;负责在网络中的两个端系统之间提供数据传输服务主要协议包括**TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;** 【2】功能 **端到端通信&#xff1a;**传输层负责…

HackerGPTWhiteRabbitNeo的使用及体验对比

1. 简介 WhiteRabbitNeo&#xff08;https://www.whiterabbitneo.com/&#xff09;是基于Meta的LLaMA 2模型进行特化的网络安全AI模型。通过专门的数据训练&#xff0c;它在理解和生成网络安全相关内容方面具有深入的专业能力&#xff0c;可广泛应用于教育、专业培训和安全研究…

什么是非电离辐射与电离辐射?

摘要: 非电离辐射和电离辐射是两种不同类型的辐射&#xff0c;它们主要区别在于能量水平和与物质相互作用的方式。 非电离辐射 非电离辐射是指能量较低&#xff0c;不足以使原子或分子的电子脱离其原子核束缚而产生电离现象的电磁波。这类辐射不 ... 非电离辐射和电离辐射是两…