【java IO】|java NIO总结

news2024/12/26 0:51:26

在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。也就是说,当一个线程执行一个 I/O 操作时,它会被阻塞直到操作完成。这种阻塞模型在处理多个并发连接时可能会导致性能瓶颈,因为需要为每个连接创建一个线程,而线程的创建和切换都是有开销的。

为了解决这个问题,在 Java1.4 版本引入了一种新的 I/O 模型(参考:浅谈IO模型) — NIO (New IO,也称为 Non-blocking IO) 。NIO 弥补了同步阻塞 I/O 的不足,它在标准 Java 代码中提供了非阻塞、面向缓冲、基于通道的 I/O,可以使用少量的线程来处理多个连接,大大提高了 I/O 效率和并发。

NIO核心组成

  • Buffer(缓冲区):NIO 读写数据都是通过缓冲区进行操作的。读操作的时候将 Channel 中的数据填充到 Buffer 中,而写操作时将 Buffer 中的数据写入到 Channel 中。
  • Channel(通道):Channel 是一个双向的、可读可写的数据传输通道,NIO 通过 Channel 来实现数据的输入输出。通道是一个抽象的概念,它可以代表文件、套接字或者其他数据源之间的连接。
  • Selector(选择器):允许一个线程处理多个 Channel,基于事件驱动的 I/O 多路复用模型。所有的 Channel 都可以注册到 Selector 上,由 Selector 来分配线程来处理事件。

关系如图所示:

Buffer(缓冲区)

在 NIO 库中,所有数据都是用缓冲区处理的,这是新库和之前的 BIO 的一个重要区别,有点类似于 BIO 中的缓冲流。NIO 在读取数据时,它是直接读到缓冲区中的。在写入数据时,写入到缓冲区中。 使用 NIO 在读写数据时,都是通过缓冲区进行操作。Buffer 的子类如下图所示。其中,最常用的是 ByteBuffer,它可以用来存储和操作字节数据。

public abstract class Buffer {
    // Invariants: mark <= position <= limit <= capacity

    // Buffer允许将位置直接定位到该标记处,这是一个可选属性;
    private int mark = -1;

    // 下一个可以被读写的数据的位置(索引)。从写操作模式到读操作模式切换的时候(flip),position 都会归零,这样就可以从头开始读写了。
    private int position = 0;

    // Buffer 中可以读/写数据的边界。写模式下,limit 代表最多能写入的数据,一般等于 capacity(可以通过limit(int newLimit)方法设置);读模式下,limit 等于 Buffer 中实际写入的数据大小。
    private int limit;

    // Buffer可以存储的最大数据量,Buffer创建时设置且不可改变;
    private int capacity;
}

Buffer 有读模式和写模式这两种模式,分别用于从 Buffer 中读取数据或者向 Buffer 中写入数据。Buffer 被创建之后默认是写模式,调用 flip() 可以切换到读模式。如果要再次切换回写模式,可以调用 clear() 或者 compact() 方法。

Buffer 常用方法:

  • get : 读取缓冲区的数据
  • put :向缓冲区写入数据
  • flip :将缓冲区从写模式切换到读模式,它会将 limit 的值设置为当前 position 的值,将 position 的值设置为 0。
  • clear: 清空缓冲区,将缓冲区从读模式切换到写模式,并将 position 的值设置为 0,将 limit 的值设置为 capacity 的值。
Channel(通道)

Channel 是一个通道,它建立了与数据源(如文件、网络套接字等)之间的连接。我们可以利用它来读取和写入数据,就像打开了一条自来水管,让数据在 Channel 中自由流动。

BIO 中的流是单向的,分为各种 InputStream(输入流)和 OutputStream(输出流),数据只是在一个方向上传输。通道与流的不同之处在于通道是双向的,它可以用于读、写或者同时用于读写。

Channel 与前面介绍的 Buffer 打交道,读操作的时候将 Channel 中的数据填充到 Buffer 中,而写操作时将 Buffer 中的数据写入到 Channel 中。

 Channel 是全双工的,所以它可以比流更好地映射底层操作系统的 API。特别是在 UNIX 网络编程模型中,底层操作系统的通道都是全双工的,同时支持读写操作。

Channel 的子类如图所示。

常用的是以下几种类型的通道:

  • FileChannel:文件访问通道;
  • SocketChannelServerSocketChannel:TCP 通信通道;
  • DatagramChannel:UDP 通信通道;

Channel 核心的两个方法:

  • read :读取数据并写入到 Buffer 中。
  • write :将 Buffer 中的数据写入到 Channel 中。

FileChannel读取文件数据:

RandomAccessFile reader = new RandomAccessFile("/Users/name/Documents/test.txt", "r"))
FileChannel channel = reader.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
Selector(选择器)

Selector(选择器) 是 NIO 中的一个关键组件,它允许一个线程处理多个 Channel。Selector 是基于事件驱动的 I/O 多路复用模型,主要运作原理是:通过 Selector 注册通道的事件,Selector 会不断地轮询注册在其上的 Channel。当事件发生时,比如:某个 Channel 上面有新的 TCP 连接接入、读和写事件,这个 Channel 就处于就绪状态,会被 Selector 轮询出来。Selector 会将相关的 Channel 加入到就绪集合中。通过 SelectionKey 可以获取就绪 Channel 的集合,然后对这些就绪的 Channel 进行响应的 I/O 操作。

一个多路复用器 Selector 可以同时轮询多个 Channel,由于 JDK 使用了 epoll() 代替传统的 select 实现,所以它并没有最大连接句柄 1024/2048 的限制。这也就意味着只需要一个线程负责 Selector 的轮询,就可以接入成千上万的客户端。

Selector 可以监听以下四种事件类型:

  • SelectionKey.OP_ACCEPT:表示通道接受连接的事件,这通常用于 ServerSocketChannel
  • SelectionKey.OP_CONNECT:表示通道完成连接的事件,这通常用于 SocketChannel
  • SelectionKey.OP_READ:表示通道准备好进行读取的事件,即有数据可读。
  • SelectionKey.OP_WRITE:表示通道准备好进行写入的事件,即可以写入数据。

Selector是抽象类,可以通过调用此类的 open() 静态方法来创建 Selector 实例。Selector 可以同时监控多个 SelectableChannel 的 IO 状况,是非阻塞 IO 的核心。

一个 Selector 实例有三个 SelectionKey 集合:

  • 所有的 SelectionKey 集合:代表了注册在该 Selector 上的 Channel,这个集合可以通过 keys() 方法返回。
  • 被选择的 SelectionKey 集合:代表了所有可通过 select() 方法获取的、需要进行 IO 处理的 Channel,这个集合可以通过 selectedKeys() 返回。
  • 被取消的 SelectionKey 集合:代表了所有被取消注册关系的 Channel,在下一次执行 select() 方法时,这些 Channel 对应的 SelectionKey 会被彻底删除,程序通常无须直接访问该集合,也没有暴露访问的方法。

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

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

相关文章

解决win10下强制设置web浏览器为microsoft edge的方法

目录 问题场景实现方法禁止edge默认选项设置默认浏览器 反思 问题场景 因为一些特殊的原因&#xff0c;我需要第二个浏览器&#xff0c;我的第一个浏览器是google的chrome浏览器&#xff0c;所以我选择的是windows的默认浏览器&#xff0c;就是microsoft edge浏览器&#xff0…

MYSQL中使用IN,在xml文件中怎么写?

MYSQL&#xff1a; Spring中&#xff1a; mysql中IN后边的集合&#xff0c;在后端中使用集合代替&#xff0c;其他的没有什么注意的&#xff0c;还需要了解foreach 语法即可。

AI抠图软件哪个好用?推荐这三款抠图工具给你

AI抠图软件哪个好用&#xff1f;你是否听说过AI抠图这个操作呢&#xff1f;简单来说&#xff0c;抠图就是一种对图像进行处理的技术&#xff0c;它的目的是将图片中的某些区域去除或者替换。比如&#xff0c;如果你有一张背景很杂乱的图片&#xff0c;你想把背景去掉&#xff0…

【Python炫酷系列】一闪一闪亮星星,漫天都是小星星(完整代码)

文章目录 环境需求完整代码详细分析系列文章环境需求 python3.11.4及以上版本PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want595.…

产品需求分析师的职责内容(合集)

产品需求分析师的职责内容1 职责&#xff1a; 1、根据公司战略规划&#xff0c;负责妇产科相关平台产品的中长期规划; 2、组织需求调研、收集、分析、整理、提炼、用户的需求&#xff0c;分析形成可行性研究报告; 3、深入挖掘产品需求&#xff0c;管理用户及公司内部业务需求&a…

深度卷积神经网络的剪枝方法

深度学习领域的一种剪枝技术是“网络瘦身&#xff08;Network Slimming&#xff09;”&#xff0c;这是一种旨在深度卷积神经网络&#xff08;CNN&#xff09;中实现通道级稀疏性的简单方案。该技术利用批量归一化中的放缩层来有效识别并修剪网络中不重要的通道。本文将详细介绍…

查看CPU的型号方法很多,而且步骤简单

每台计算机至少包含一个处理器&#xff0c;也称为CPU或中央处理单元。你电脑的CPU可能是由英特尔或AMD制造的。以下是如何查看你的CPU以及它的速度。 在设置应用程序中查找你的CPU 要在Windows 10或Windows 11设置应用程序中查找此信息&#xff0c;请导航到“设置”>“系统…

黑盒测试中关键截图如何打点

黑盒测试中关键截图如何打点Android黑盒测试过程中如何进行有效的打点是我们经常遇到的问题&#xff0c;我们一般会在脚本内部进行数据打点&#xff0c;也可以使用其他进程录屏或截图。那我们如何选取合适的方式进行打点记录呢&#xff1f;下图是对常用打点方式的统计&#xff…

全链路压力测试:解析其主要特点

随着信息技术的飞速发展和云计算的普及&#xff0c;全链路压力测试作为一种关键的质量保障手段&#xff0c;在软件开发和系统部署中扮演着至关重要的角色。全链路压力测试以模拟真实生产环境的压力和负载&#xff0c;对整个业务流程进行全面测试&#xff0c;具有以下主要特点&a…

openGauss学习笔记-164 openGauss 数据库运维-备份与恢复-导入数据-使用COPY FROM STDIN导入数据-处理错误表

文章目录 openGauss学习笔记-164 openGauss 数据库运维-备份与恢复-导入数据-使用COPY FROM STDIN导入数据-处理错误表164.1 操作场景164.2 查询错误信息164.3 处理数据导入错误 openGauss学习笔记-164 openGauss 数据库运维-备份与恢复-导入数据-使用COPY FROM STDIN导入数据-…

鸿蒙(HarmonyOS)应用开发—— video组件实操

video 组件 harmonyOS 系统提供了基础的video。下面就直接上代码 原始video 新建项目 customVideo项目 本地视频 网络地址&#xff0c;就不用说明&#xff0c;只需要把地址换成网络地址即可 在resource 文件夹下的rawfile文件夹下 添加视频 在index.ets Video({src:$rawf…

C++数据结构——二叉搜索树详解

目录 一&#xff0c;关于二叉搜索树 1.1 概念 1.2 基本结构 二&#xff0c;二叉搜索树接口实现 2.1 插入 2.2 查找 2.3 打印 2.4* 删除 三&#xff0c;二叉搜索树接口递归实现 3.1 查找 3.2 插入 3.3 删除 四&#xff0c;二叉搜索树的默认成员函数 五&#xff0c;…

一篇文章带你了解各个程序员接单平台,让你选择不再迷茫!!!

相信现在很多程序员都已经走上了或者准备走上网上接单这条路&#xff0c;但是目前市面上的接单平台可谓五花八门&#xff0c;对于各个平台的优缺点&#xff0c;不同的程序员该如何选择适合自己的接单平台&#xff0c;你又是否了解呢&#xff1f; 接下来就让小编用一篇文章来为…

定位咨询:企业市场竞争中的定海神针

什么是定位咨询?定位咨询能给企业带来什么帮助?在现代市场的激烈竞争中&#xff0c;定位咨询不仅是企业区分自己的重要工具&#xff0c;更是它们赢得市场份额的关键。以下是定位咨询的定义和几个核心方面&#xff0c;笔者将列举具体案例说明其重要性和实用性。 定位咨询的简单…

python接口自动化测试--requests使用和基本方法封装

之前学习了使用jmeterant做接口测试&#xff0c;并实现了接口的批量维护管理(大概500多条用例)&#xff0c;对“接口”以及“接口测试”有了一个基础了解&#xff0c;最近找了一些用python做接口测试的资料&#xff0c;一方面为了学习下如何使用python进行接口测试(如何做出一个…

券商期权手续费现在最低多少钱一张?怎么调低最方便

券商期权手续费是指您在证券公司开设期权账户并进行期权交易时&#xff0c;需要向券商支付的费用。券商期权手续费主要包括以下三个部分&#xff1a; 中国结算费用&#xff1a;这是中国证券登记结算有限责任公司向期权交易者收取的费用&#xff0c;固定为每张合约0.3元&#x…

GPT-4V with Emotion:A Zero-shot Benchmark forMultimodal Emotion Understanding

GPT-4V with Emotion:A Zero-shot Benchmark forMultimodal Emotion Understanding GPT-4V情感:多模态情感理解的zero-shot基准 1.摘要 最近&#xff0c;GPT-4视觉系统(GPT-4V)在各种多模态任务中表现出非凡的性能。然而&#xff0c;它在情感识别方面的功效仍然是个问题。本文定…

Crocoddyl: 多接触最优控制的高效多功能框架

系列文章目录 前言 我们介绍了 Crocoddyl&#xff08;Contact RObot COntrol by Differential DYnamic Library&#xff09;&#xff0c;这是一个专为高效多触点优化控制&#xff08;multi-contact optimal control&#xff09;而定制的开源框架。Crocoddyl 可高效计算给定预定…

将yolo格式转化为voc格式:txt转xml(亲测有效)

1.文件目录如下所示&#xff1a; 对以上目录的解释&#xff1a; 1.dataset下面的image文件夹&#xff1a;里面装的是数据集的原图片 2.dataset下面的label文件夹&#xff1a;里面装的是图片对应得yolo格式标签 3.dataset下面的Annotations文件夹&#xff1a;这是一个空文件夹&…

通过与 Team Finance 整合,Casper Network 让 Token 的创建、部署更加高效

随着 Team Finance 整合到 Casper 系统中&#xff0c;Token 创建的过程变得更加迅速而简便。Casper Network 的方案正在使代币的创建变得易于访问与调整&#xff0c;这将让任何有创意和业务理念的人能够以高效、可信的方式&#xff0c;更快速、安全地在 Casper 上推出他们的项目…