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/630126.shtml

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

相关文章

Python 算术运算符:解码数字世界的算术密码

算术运算是计算机编程中最基本和常见的运算之一。在 Python 中,算术运算符提供了一组功能强大的操作符,使得我们能够对数字进行加减乘除等各种数学计算。本文将深入探讨 Python 中的算术运算符,包括常见的算术运算符、使用注意事项以及在实际…

线性回归理论+实战

线性回归 什么是线性回归 3.1. 线性回归 — 动手学深度学习 2.0.0 documentation (d2l.ai) 模型 损失函数 模型拟合(fit)数据之前,我们需要确定一个拟合程度的度量。 损失函数(loss function)能够量化目标的实际值…

导入失败,报错:“too many filtered rows xxx, “ErrorURL“:“

一、问题: 注:前面能正常写入,突然就报错,导入失败,报错:“too many filtered rows xxx, "ErrorURL":" {"TxnId":769494,"Label":"datax_doris_writer_bf176078-…

物联网中的通信技术

阅读引言: 本文主要大致为大家带来物联网中的常见的通信方式的知识梳理。 目录 一、概述 二、无线通信技术 1.物联网电子标签 RFID 1.1 RFID 概念 1.2 RFID 系统组成 2.WI-FI技术 3.UWB技术 4.ZigBee技术 5.NFC技术 6.蓝牙技术 7.EnOcean技术 一、概述 物…

【服务器数据恢复】服务器迁移数据时lun数据丢失的数据恢复案例

服务器数据恢复环境&服务器故障: 一台安装Windows操作系统的服务器。工作人员在迁移该服务器中数据时突然无法读取数据,服务器管理界面出现报错。经过检查发现服务器中一个lun的数据丢失。 服务器数据恢复过程: 1、将故障服务器中所有磁盘…

SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源

场景 dynamic-datasource-spring-boot-starter实现动态数据源Mysql和Sqlserver: dynamic-datasource-spring-boot-starter实现动态数据源Mysql和Sqlserver_dynamic-datasource-spring-boot-starter mysql sqlse-CSDN博客 SpringBoot中整合MybatisPlus快速实现Mys…

利用docker的LNMP

目录 服务器环境 任务需求 服务搭建 Nginx Mysql Php 启动 wordpress 服务 服务器环境 容器 操作系统 IP地址 主要软件 nginx CentOS 7 172.20.0.10 Docker-Nginx mysql CentOS 7 172.20.0.20 Docker-Mysql php CentOS 7 172.2…

详解ISIS动态路由协议

华子目录 前言应用场景历史起源ISIS路由计算过程ISIS的地址结构ISIS路由器分类ISIS邻居关系的建立P2PMA ISIS中的DIS与OSPF中DR的对比链路状态信息的交互ISIS的最短路径优先算法(SPF)ISIS区域划分ISIS区域间路由访问原理ISIS与OSPF的不同ISIS与OSPF的术语…

Asp .Net Core 系列:集成 Ocelot+Consul实现网关、服务注册、服务发现

什么是Ocelot? Ocelot是一个开源的ASP.NET Core微服务网关,它提供了API网关所需的所有功能,如路由、认证、限流、监控等。 Ocelot是一个简单、灵活且功能强大的API网关,它可以与现有的服务集成,并帮助您保护、监控和扩展您的微…

如何安装下载激活MathType?2024最新免费MathType许可证

第一步:请先从这里下载安装MathType: 第二步:下载完成后,双击下载的MathType Desktop安装程序文件。 在Mac上,这将在单独的窗口中打开它,因此在该窗口中双击“ MathType Desktop Installer…”以运行安装…

TQ7.2WS acid,Tide Quencher 7.2WS 酸,能够降低荧光信号的强度

您好,欢迎来到新研之家 文章关键词:Tide Quencher 7.2WS acid,TQ7.2WS acid,Tide Quencher 7.2WS 酸 ,TQ7.2WS 酸 一、基本信息 产品简介:The fluorescence quenching agent Tide Quencher 7.2WS acid h…

win10 系统维护

电脑崩溃之后,我发现维护系统还是很重要的一件事情。比如软件尽可能装D盘,C盘(系统盘)尽可能不要存储数据等等。接着,就是如何让系统更易用,因此我在这里分享我的使用方式,以后就可以随便重装系…

微信小程序防止截屏录屏

一、使用css添加水印 使用微信小程序原生的view和css给屏幕添加水印这样可以防止用户将小程序内的隐私数据进行截图或者录屏分享导致信息泄露,给小程序添加一个水印浮层。这样即使被截图或者拍照,也能轻松地确定泄露的源头。效果图如下: 代码…

LeetCode刷题---基本计算器

解题思路: 根据题意,字符串中包含的运算符只有和- 使用辅助栈的方法来解决该问题 定义结果集res和符号位sign(用于判断对下一数的加减操作),接着对字符串进行遍历。 如果当前字符为数字字符,判断当前字符的下一个字符是否也是数字字符&#x…

计算机网络-NAT网络地址转换

今天来回顾下之前所学的知识,将它们串联起来进行巩固。一开始了解了IP编址进行IP设置和划分网段;学习了二层以太网交换,了解了二层通信基础;学习了路由基础知识,大致了解到了路由是什么?静态路由和动态路由…

【MIdjourney】几种独特的艺术风格

1.合成器波(Synthwave) Synthwave是一种音乐风格,起源于20世纪80年代电子音乐和电影的复古元素。这种音乐风格通常包括合成器音乐、电子鼓声和强烈的电子声效,以模拟80年代电影和视频游戏的声音。Synthwave的特点包括浓厚的合成器声音、强烈的节奏和对复…

工商业屋顶光伏项目如何操作?

鹧鸪云 随着可再生能源的日益重要,工商业屋顶光伏项目已成为许多企业实现绿色能源转型的重要途径。本文将详细介绍工商业屋顶光伏项目的操作流程,帮助企业更好地实施这一项目。 一、项目前期准备 需求分析:明确企业的能源需求,评…

JNI笔记

JNI笔记 背景Demo代码JNI.javaMainActivity.javaAndroid.mkApplication.mkcom_stone_javacallc_JNI.hjavacallc.cbuild.gradle 背景 Demo代码 代码结构 JNI.java package com.stone.javacallc;/*** Created by stoneWang* Created on 2024/1/16* java调用C*/ public class …

mysql从库重新搭建的流程

背景 生产环境上的主从集群,因为一些异常原因,导致主从同步失败。现记录下通过重做mysql从库的方式来解决,重做过程不影响主库。 步骤 1、在主库上的操作步骤 备份主库所有数据,并将dump.sql文件拷贝到从库/tmp目录 mysqldump …

【车载HMI开发工具--EB GUIDE介绍】

EB GUIDE 是作为当今的汽车内一些最佳行业用户界面的技术。利用 EB GUIDE,您可以创建最佳的信息娱乐系统和仪表板的人机交互界面。EB GUIDE 不仅仅是一个工具,它还能支持汽车软件开发过程,从而创造出世界一流的汽车 HMI。 优点 在开发过程中…