Java NIO 深度解析:构建高效的 I/O 操作
在 Java 编程领域,I/O 操作一直是至关重要的部分,它直接影响着应用程序的性能和响应能力。Java NIO(New I/O)作为传统 I/O 的增强版本,为处理大量并发连接和高效的数据传输提供了更强大的工具和机制。本文将深入探讨 Java NIO 的核心概念、关键组件以及如何运用它来构建高性能的 I/O 应用程序。
一、Java NIO 概述
Java NIO 是在 Java 1.4 中引入的一套全新的 I/O API,它与传统的 Java I/O(基于流的 I/O)有所不同。NIO 采用了基于通道(Channel)和缓冲区(Buffer)的非阻塞式 I/O 模型,这种模型能够在处理大量并发连接时表现出更好的性能和可扩展性。
传统的 I/O 操作在进行数据读取或写入时,往往会阻塞当前线程,直到操作完成。这在处理高并发场景时,会导致大量线程处于等待状态,浪费系统资源并降低应用程序的吞吐量。而 Java NIO 的非阻塞特性允许线程在等待 I/O 操作完成的过程中执行其他任务,从而提高了系统的资源利用率和响应速度。
二、核心组件
1. 通道(Channel)
通道是 NIO 中数据传输的载体,类似于传统 I/O 中的流,但具有更高的抽象层次和更多的功能。通道可以用于读取和写入数据,并且支持双向操作。常见的通道类型包括:
- FileChannel:用于文件的读写操作。可以从文件中读取数据到缓冲区,或者将缓冲区中的数据写入到文件。
- SocketChannel:用于网络套接字的读写操作。可以与远程服务器建立连接,并进行数据传输。
- ServerSocketChannel:用于监听网络端口,接受客户端的连接请求,并创建对应的
SocketChannel
实例。
例如,使用 FileChannel
读取文件的示例代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class FileChannelExample {public static void main(String[] args) {try {File file = new File("test.txt");FileInputStream fis = new FileInputStream(file);FileChannel channel = fis.getChannel();ByteBuffer buffer = ByteBuffer.allocate((int) file.length());channel.read(buffer);buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}channel.close();fis.close();} catch (IOException e) {e.printStackTrace();}}
}
在上述示例中,首先通过 FileInputStream
获取对应的 FileChannel
,然后创建一个 ByteBuffer
缓冲区,将文件数据读取到缓冲区中,并最后将缓冲区中的数据打印出来。
2. 缓冲区(Buffer)
缓冲区是用于存储数据的容器,在 NIO 中所有的数据读写操作都是通过缓冲区来完成的。缓冲区具有以下几个重要属性:
- 容量(Capacity):缓冲区能够容纳的最大数据量。
- 位置(Position):当前缓冲区中数据的读写位置。
- 限制(Limit):缓冲区中可操作数据的边界。
常见的缓冲区类型有 ByteBuffer
、CharBuffer
、IntBuffer
等,分别用于处理不同类型的数据。例如,ByteBuffer
可以用于存储字节数据,适用于大多数通用的 I/O 操作。
以下是一个简单的 ByteBuffer
使用示例,展示了数据的写入和读取过程:
import java.nio.ByteBuffer;public class ByteBufferExample {public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(1024);// 写入数据到缓冲区buffer.put((byte) 'H');buffer.put((byte) 'e');buffer.put((byte) 'l');buffer.put((byte) 'l');buffer.put((byte) 'o');// 切换缓冲区为读模式buffer.flip();// 从缓冲区读取数据while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}}
}
在这个示例中,首先分配了一个容量为 1024 的 ByteBuffer
,然后向其中写入了字符串 "Hello" 的字节数据,接着通过 flip
方法切换缓冲区为读模式,最后循环读取并打印缓冲区中的数据。
3. 选择器(Selector)
选择器是 NIO 实现非阻塞 I/O 的关键组件。它可以同时监听多个通道的事件,例如连接就绪、读就绪、写就绪等事件。通过使用选择器,单个线程可以管理多个通道的 I/O 操作,从而实现高效的并发处理。
以下是一个使用 Selector
实现简单的网络服务器示例,该服务器可以同时处理多个客户端连接:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class NIOServer {public static void main(String[] args) throws IOException {// 创建 ServerSocketChannelServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(8888));serverSocketChannel.configureBlocking(false);// 创建 SelectorSelector selector = Selector.open();// 将 ServerSocketChannel 注册到 Selector 上,监听连接事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {// 阻塞等待事件发生selector.select();// 获取发生事件的 SelectionKey 集合Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();iterator.remove();if (key.isAcceptable()) {// 处理连接事件ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);// 将新连接的 SocketChannel 注册到 Selector 上,监听读事件socketChannel.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {// 处理读事件SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int numRead = socketChannel.read(buffer);if (numRead == -1) {// 客户端关闭连接socketChannel.close();} else {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("Received from client: " + new String(data));// 处理完数据后,将数据写回客户端buffer.flip();socketChannel.write(buffer);}}}}}
}
在这个示例中,首先创建了 ServerSocketChannel
并绑定到指定端口,将其设置为非阻塞模式后注册到 Selector
上监听连接事件。然后进入一个循环,通过 selector.select()
阻塞等待事件发生。当有事件发生时,遍历 selectedKeys
集合,根据事件类型分别处理连接事件和读事件。对于读事件,从客户端读取数据并打印,然后将数据写回客户端。
三、NIO 的优势与应用场景
1. 优势
- 非阻塞 I/O:减少线程阻塞等待时间,提高系统资源利用率和并发处理能力。
- 缓冲区操作:直接对缓冲区进行数据处理,减少数据复制次数,提高数据传输效率。
- 多路复用:通过选择器实现单个线程管理多个通道,降低系统开销,适用于高并发网络应用。
2. 应用场景
- 网络编程:如高性能的 Web 服务器、网络代理服务器、即时通讯软件等,需要处理大量并发连接的场景。
- 文件处理:对于大文件的读写操作,NIO 能够提供更高效的方式,例如文件上传下载、文件系统监控等。
四、总结
Java NIO 通过引入通道、缓冲区和选择器等核心组件,为 Java 开发者提供了一种高效、灵活的 I/O 处理方式。它在处理高并发和大数据量的 I/O 操作时表现出色,能够显著提升应用程序的性能和可扩展性。理解和掌握 Java NIO 的原理和使用方法,对于开发高性能的网络应用和处理大规模数据的程序具有重要意义。希望本文能够帮助读者深入了解 Java NIO,并在实际项目中充分发挥其优势,构建出更加健壮和高效的 Java 应用程序。
相关文章:
Java NIO 深度解析:构建高效的 I/O 操作
在 Java 编程领域,I/O 操作一直是至关重要的部分,它直接影响着应用程序的性能和响应能力。Java NIO(New I/O)作为传统 I/O 的增强版本,为处理大量并发连接和高效的数据传输提供了更强大的工具和机制。本文将深入探讨 J…...

总结拓展十六:特殊采购业务——VMI采购模式
1、VMI的定义 VMI采购模式(Vendor Managed Inventory)是一种合作性策略,旨在通过供应商管理库存,使供应链中的企业和供应商双方都能获得最低成本。在这种模式下,供应商根据共享的用户企业库存和实际耗用数据&#x…...
vue2 + iview(view-design) 中封装使用 vxe-table 处理表格渲染大量数据卡顿现象
今天遇到需求,iview组件分页每页100页时候页面卡顿现象严重,改造为使用vxe-table cell-mouseenter"handleCellMouseEnter" cell-mouseleave"handleCellMouseLeave" 这两个用来处理vxe-table 内容过多鼠标悬浮上去滚动 tooltip直接…...

初学者指南:知识库问答(KBQA)多跳路径的核心与应用
初学者指南:知识库问答(KBQA)多跳路径的核心与应用 知识库问答(Knowledge Base Question Answering, KBQA)旨在利用结构化知识库(如Wikidata、Freebase)回答自然语言问题。在实际应用中&#x…...

创建springboot+vue项目相关配置问题
安装并配置jdk23 在官网下载jdk Java Downloads | Oracle 中国 下载完成后双击即可安装。 安装完成后配置环境变量 此电脑->右键->属性->高级系统设置 然后一直点击确定即可。 键盘上win r java -version 可以验证是否配置成功 下载并配置maven 在官网下…...

基于AOA算术优化的KNN数据聚类算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于AOA算术优化的KNN数据聚类算法matlab仿真。通过AOA优化算法,搜索最优的几个特征数据,进行KNN聚类,同时对比不同个数特征下…...

【机器学习】在泊松分布中,当λ值较大时,其近似正态分布的误差如何评估?
在泊松分布中,当参数 λ 较大时,其近似正态分布的有效性可以通过 中心极限定理 和误差分析来理解和评估。以下内容结合理论推导和实际案例展开说明: 1. 泊松分布的定义 泊松分布是用于建模单位时间或单位空间内随机事件发生次数的概率分布&a…...

ABAP开发-面向对象开发_2
系列文章目录 文章目录 系列文章目录[TOC](文章目录) 前言接口和类1、首先创建一个接口2、在创建的接口的基础上创建一个类PERSON3、创建子类STUDENT4、创建子类TEACHER5、SE38使用创建的类 总结 前言 接口和类 全局类 SE24 创建一个接口-》创建一个实现接口的类-》再创建两个…...

微信小程序-prettier 格式化
一.安装prettier插件 二.配置开发者工具的设置 配置如下代码在setting.json里: "editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","prettier.documentSelectors": ["**/*.wxml"…...
241118学习日志——[CSDIY] [ByteDance] 后端训练营 [06]
CSDIY:这是一个非科班学生的努力之路,从今天开始这个系列会长期更新,(最好做到日更),我会慢慢把自己目前对CS的努力逐一上传,帮助那些和我一样有着梦想的玩家取得胜利!!&…...

Android WMS概览
WMS(WindowManagerService)是 Android 系统的核心服务,负责管理应用和系统的窗口,包括窗口的创建、销毁、布局、层级管理、输入事件分发以及动画显示等。它通过协调 InputManager 和 SurfaceFlinger 实现触摸事件处理和窗口渲染&a…...

新一代API开发工具,让API调试更快 更简单
新一代API开发工具 代理调试 请求测试一站式解决方案 Reqable Fiddler Charles Postman, 让API调试更快 🚀 更简单 👌 直接上下载地址 根据系统,下载对应的版本即可 https://reqable.com/zh-CN/download/...
友元类和友元函数
友元函数的定义: 友元函数是在类定义中被声明为 “朋友” 的非成员函数。它可以访问类的私有成员和保护成员(变量和方法),就好像它是类的成员函数一样。友元函数的声明以friend关键字开头,在类的内部进行声明,但它的定义在类的外部ÿ…...

Sulfo-Cy5-Iodoacetamide能够发出明亮的荧光信号,使得生物样本的精细结构得以清晰呈现
一、基本信息 英文名称:Sulfo-Cy5-Iodoacetamide,Sulfo-Cyanine5-Iodoacetamide,Sulfo Cy5 IA 中文名称:磺酸Cy5碘乙酰胺 分子式:C36H44IKN4O8S2 分子量:890.89 纯度:≥95% 外观ÿ…...

Python中的TCP
文章目录 一. 计算机网络1. 网络的概念2. IP地址① IP地址的概念② IP地址的表现形式③ IP地址的作用④ 网络查询命令Ⅰ. ifconfig/ipconfigⅡ. ping 3. 端口和端口号的概念(计算机通信原理)① 端口的概念② 端口号的概念 4. socket套接字① socket概念② socket使用场景 二. T…...

CSS(8)高级技巧:精灵图,css三角,用户界面,vertical-align属性应用
一.精灵图 通过css中的background-position属性,将多张图合成为一张图 二.css三角 在网页中,我们可以添加css属性获得三角图标 solid:实心,边框的实心 transparent:透明,图中代码表示只有左边粉色,其余地方为透明 三ÿ…...

Flink新版Source接口源码解析
目录 1. 前言 2. Source解析 2.1 Source类图 2.2 接口和方法说明 2.2.1 Source,> 3. SplitEnumerator解析 3.1 SplitEnumetator类图 3.2 类和方法说明 3.2.1 SplitEnumerator 3.2.2 SimpleVersionedSerializer 4. SourceReader解析 4.1 SourceReader类图 4.2 类…...

SLM561A系列60V10-50mA单通道线性恒流LED驱动芯片,为汽车照明、景观照明助力
SLM561A系列选型参考: SLM561A10ae-7G SOD123 SLM561A15ae-7G SOD123 SLM561A20ae-7G SOD123 SLM561A25ae-7G SOD123 SLM561A30ae-7G SOD123 SLM561A35ae-7G SOD123 SLM561A40ae-7G SOD123 SLM561A45ae-7G SOD123 SLM561A50ae-7G SOD123 S…...

一次失败的wxpython安装macOS M1
WARNING: The scripts libdoc, rebot and robot are installed in /Users/用户名/Library/Python/3.8/bin which is not on PATH. 背景:想在macos安装Robot Framework ,显示pip3不是最新,更新pip3后显示不在PATH上 参看博主文章末尾 MAC系统…...

【大数据技术基础 | 实验十一】Hive实验:新建Hive表
文章目录 一、实验目的二、实验要求三、实验原理四、实验环境五、实验内容和步骤(一)启动Hive(二)创建表(三)显示表(四)显示表列(五)更改表(六&am…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

使用VMware克隆功能快速搭建集群
自己搭建的虚拟机,后续不管是学习java还是大数据,都需要集群,java需要分布式的微服务,大数据Hadoop的计算集群,如果从头开始搭建虚拟机会比较费时费力,这里分享一下如何使用克隆功能快速搭建一个集群 先把…...

Ubuntu 安装 Mysql 数据库
首先更新apt-get工具,执行命令如下: apt-get upgrade安装Mysql,执行如下命令: apt-get install mysql-server 开启Mysql 服务,执行命令如下: service mysql start并确认是否成功开启mysql,执行命令如下&am…...