如何在Java中使用NIO框架?

news/2025/11/27 18:58:32/文章来源:https://www.cnblogs.com/dunzhujiao/p/19279142
在 Java 中使用 NIO 框架(Java NIO)需掌握其核心组件(Buffer、Channel、Selector)及非阻塞 I/O 模型。以下从基础组件使用文件操作网络通信高级封装框架四个维度,结合示例详解具体用法:

一、Java NIO 核心组件基础

Java NIO 的核心是Buffer(缓冲区)Channel(通道)Selector(选择器),三者协同实现非阻塞 I/O:
  • Buffer:数据容器,用于存储待读写的数据(如 ByteBuffer、CharBuffer);
  • Channel:双向数据通道(连接数据源与 Buffer),支持非阻塞操作(如 FileChannel、SocketChannel);
  • Selector:多路复用器,让单线程监听多个 Channel 的 I/O 事件(如连接、可读、可写)。

二、NIO 文件操作(FileChannel)

FileChannel 用于文件的读写,支持阻塞 / 非阻塞模式,性能优于传统 FileInputStream/FileOutputStream。

1. 读取文件

java
 
运行
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;public class NIOFileReadExample {public static void main(String[] args) {try (// 以读写模式打开文件RandomAccessFile file = new RandomAccessFile("data.txt", "rw");// 获取文件通道FileChannel channel = file.getChannel()) {// 分配缓冲区(容量1024字节)ByteBuffer buffer = ByteBuffer.allocate(1024);// 从通道读取数据到缓冲区int bytesRead = channel.read(buffer);while (bytesRead != -1) { // -1表示读取完毕// 切换缓冲区为"读模式"(limit=position,position=0)buffer.flip();// 读取缓冲区数据(转换为字符串)String content = StandardCharsets.UTF_8.decode(buffer).toString();System.out.print(content);// 清空缓冲区(切换为"写模式",position=0,limit=capacity)buffer.clear();// 继续读取下一批数据bytesRead = channel.read(buffer);}} catch (Exception e) {e.printStackTrace();}}
}
 

2. 写入文件

java
 
运行
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;public class NIOFileWriteExample {public static void main(String[] args) {try (RandomAccessFile file = new RandomAccessFile("output.txt", "rw");FileChannel channel = file.getChannel()) {String data = "Hello Java NIO!";// 将字符串转为字节数组,写入缓冲区ByteBuffer buffer = ByteBuffer.wrap(data.getBytes(StandardCharsets.UTF_8));// 从缓冲区写入通道(即写入文件)channel.write(buffer);System.out.println("数据写入完成");} catch (Exception e) {e.printStackTrace();}}
}
 

3. 文件复制(通道直接传输)

FileChannel 支持transferFrom()/transferTo()直接传输数据,无需缓冲区中转,效率更高:
java
 
运行
 
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;public class NIOFileCopyExample {public static void main(String[] args) {try (RandomAccessFile sourceFile = new RandomAccessFile("source.txt", "r");RandomAccessFile targetFile = new RandomAccessFile("target.txt", "rw");FileChannel sourceChannel = sourceFile.getChannel();FileChannel targetChannel = targetFile.getChannel()) {// 从源通道传输数据到目标通道(参数:起始位置,传输大小,目标通道)sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);System.out.println("文件复制完成");} catch (Exception e) {e.printStackTrace();}}
}
 

三、NIO 网络通信(Selector + SocketChannel)

Java NIO 的核心优势是非阻塞网络通信,通过 Selector 实现单线程处理多连接,适用于高并发场景(如服务器开发)。

1. NIO 服务器端(支持多客户端连接)

java
 
运行
 
 
 
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;public class NIOServer {public static void main(String[] args) {try (// 打开Selector(多路复用器)Selector selector = Selector.open();// 打开服务器通道(ServerSocketChannel)ServerSocketChannel serverChannel = ServerSocketChannel.open()) {// 绑定端口serverChannel.bind(new InetSocketAddress(8080));// 设置为非阻塞模式(必须,否则Selector无法工作)serverChannel.configureBlocking(false);// 注册"连接事件"(OP_ACCEPT)到SelectorserverChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("NIO服务器启动,监听端口8080...");while (true) {// 阻塞等待事件触发(返回触发的事件数)int readyChannels = selector.select();if (readyChannels == 0) continue;// 获取所有触发的事件KeySet<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 处理"连接事件"(客户端发起连接)if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 接受客户端连接,返回SocketChannelSocketChannel clientChannel = ssc.accept();clientChannel.configureBlocking(false);// 注册"读事件"(OP_READ)到Selector,关联一个缓冲区clientChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));System.out.println("客户端连接:" + clientChannel.getRemoteAddress());}// 处理"读事件"(客户端发送数据)else if (key.isReadable()) {SocketChannel clientChannel = (SocketChannel) key.channel();// 获取关联的缓冲区ByteBuffer buffer = (ByteBuffer) key.attachment();// 从通道读取数据到缓冲区int bytesRead = clientChannel.read(buffer);if (bytesRead == -1) {// 客户端关闭连接clientChannel.close();key.cancel();System.out.println("客户端断开连接:" + clientChannel.getRemoteAddress());continue;}// 切换缓冲区为读模式buffer.flip();// 解码数据为字符串String msg = StandardCharsets.UTF_8.decode(buffer).toString().trim();System.out.println("收到客户端消息:" + msg);// 回复客户端(可选)String response = "服务器已收到:" + msg;buffer.clear();buffer.put(response.getBytes(StandardCharsets.UTF_8));buffer.flip();clientChannel.write(buffer);// 清空缓冲区,准备下次读取buffer.clear();}// 移除已处理的事件Key(必须,否则会重复处理)keyIterator.remove();}}} catch (IOException e) {e.printStackTrace();}}
}
 

2. NIO 客户端(连接服务器并发送数据)

java
 
运行
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;public class NIOClient {public static void main(String[] args) {try (// 打开SocketChannelSocketChannel clientChannel = SocketChannel.open();Scanner scanner = new Scanner(System.in)) {// 连接服务器clientChannel.connect(new InetSocketAddress("localhost", 8080));// 设置为非阻塞模式(可选,若需异步操作)clientChannel.configureBlocking(false);ByteBuffer buffer = ByteBuffer.allocate(1024);System.out.println("已连接服务器,输入消息发送(输入exit退出):");while (true) {String msg = scanner.nextLine();if ("exit".equalsIgnoreCase(msg)) break;// 写入数据到缓冲区buffer.put(msg.getBytes(StandardCharsets.UTF_8));buffer.flip();// 发送数据到服务器clientChannel.write(buffer);buffer.clear();// 读取服务器回复(非阻塞模式需循环读取)int bytesRead = clientChannel.read(buffer);if (bytesRead > 0) {buffer.flip();String response = StandardCharsets.UTF_8.decode(buffer).toString();System.out.println("服务器回复:" + response);buffer.clear();}}} catch (IOException e) {e.printStackTrace();}}
}
 

四、使用高级 NIO 封装框架(Netty)

Java NIO 原生 API 较繁琐,实际开发中常使用Netty(基于 NIO 封装的高性能网络框架),简化开发流程:

1. Netty 服务器端示例

java
 
运行
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class NettyServer {public static void main(String[] args) throws InterruptedException {// 主线程组(接受连接)EventLoopGroup bossGroup = new NioEventLoopGroup(1);// 工作线程组(处理读写)EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 使用NIO通道.option(ChannelOption.SO_BACKLOG, 128) // 连接队列大小.childOption(ChannelOption.SO_KEEPALIVE, true) // 保持长连接.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 添加字符串编解码器pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());// 添加自定义业务处理器pipeline.addLast(new NettyServerHandler());}});// 绑定端口并启动ChannelFuture future = bootstrap.bind(8080).sync();System.out.println("Netty服务器启动,监听端口8080...");// 等待服务器关闭future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}// 自定义业务处理器static class NettyServerHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println("收到客户端消息:" + msg);// 回复客户端ctx.writeAndFlush("服务器已收到:" + msg);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端连接:" + ctx.channel().remoteAddress());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}}
}
 

2. Netty 客户端示例

java
 
运行
 
 
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;import java.util.Scanner;public class NettyClient {public static void main(String[] args) throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());pipeline.addLast(new NettyClientHandler());}});// 连接服务器ChannelFuture future = bootstrap.connect("localhost", 8080).sync();Channel channel = future.channel();System.out.println("已连接服务器,输入消息发送(输入exit退出):");Scanner scanner = new Scanner(System.in);while (true) {String msg = scanner.nextLine();if ("exit".equalsIgnoreCase(msg)) {channel.close();break;}// 发送消息channel.writeAndFlush(msg);}channel.closeFuture().sync();} finally {group.shutdownGracefully();}}static class NettyClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println("服务器回复:" + msg);}}
}
 

五、NIO 使用注意事项

  1. Buffer 操作:务必区分 “写模式” 和 “读模式”(通过flip()切换),避免数据读取错误;
  2. 非阻塞模式:Channel 需设置为configureBlocking(false)才能配合 Selector 使用;
  3. Selector 事件处理:处理完事件后必须移除SelectionKeykeyIterator.remove()),否则会重复触发;
  4. 资源释放:Channel、Selector 需通过try-with-resources或手动关闭,避免资源泄漏;
  5. 高并发场景:优先使用 Netty 等封装框架,避免原生 NIO 的复杂细节。

总结

Java NIO 通过 Buffer、Channel、Selector 实现非阻塞 I/O,适用于文件操作和高并发网络通信。原生 API 需手动管理缓冲区和事件,而 Netty 等框架封装了底层细节,大幅提升开发效率。根据场景选择:简单文件操作可用原生 FileChannel,高并发网络开发优先用 Netty。

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

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

相关文章

告别老花镜,视力再年轻!明基医院太学眼科老花门诊成立

11月27日,明基医院太学眼科迎来历史性时刻——"近视老花门诊"与"老花白内障门诊"正式揭牌成立。这不仅是一次简单的门诊增设,更是对传统老视诊疗模式的重要革新,标志着医院在全程眼健康领域迈出…

2025年高中培训机构评估指南,高考最后冲刺靠谱的培训机构推荐

在高考这场没有硝烟的战争中,每一位考生都渴望找到那把打开理想大学之门的钥匙。选择一家合适的培训机构,就如同为这场战役配备了精良的装备。今天,我们就来聊聊五家在高考冲刺阶段备受好评的培训机构,其中,高途教…

返回值类

/// <summary>/// 返回值类/// </summary>public class ActionResult{private bool isSuccess = false;private string message = string.Empty;private int erroCode = 0;public bool IsSuccess { get =&…

为什么说白瑞芳是最适合基础巩固的高中数学老师?

“数学课从不敢抬头到主动举手,从畏惧考试到期待挑战”,这不仅是成绩的提升,更是学习信心的重塑。 在高中数学学习道路上,基础薄弱的学生最需要的不是解题技巧的灌输,而是对数学信心的重建和知识体系的扎实搭建。…

全自动滤水器厂家推荐:连云港华博与博璟源的专业之选

全自动滤水器厂家推荐:连云港华博与博璟源的专业之选 在工业循环水、市政供水或民用净水场景中,全自动滤水器的稳定性、过滤效率与维护成本,直接影响生产连续性与用户体验——堵塞停机、频繁换芯、过滤精度不达标等…

别再闹笑话了!OpenPLC ≠ PLCopen,一文讲透真正的区别

​在工控圈,有两个名字常常被放在一起讨论——OpenPLC 和 PLCopen。名字长得像、都和 PLC 有关、都经常出现在自动化论坛上。于是就出现了一种奇怪的现象: 很多工程师第一次看到时都会冒出同一句话:“这俩不就是一个…

全自动工业滤水器厂家推荐:连云港华博与博璟源的专业之选

全自动工业滤水器厂家推荐:连云港华博与博璟源的专业之选 在化工、电力、冶金等工业领域,水质中的悬浮颗粒、杂质若未有效过滤,易导致管道堵塞、设备腐蚀、产能下降,甚至引发停机事故,给企业造成巨大经济损失。选…

美容院选择皮肤检测仪的5大标准:安德颜析MINI如何满足专业需求

作为美容院、医美机构、皮肤管理中心的经营者,你是否正在考虑引入皮肤检测设备?在科学护肤理念深入人心的今天,一台专业的皮肤检测仪已经不是"可有可无"的工具,而是提升竞争力的"战略武器"。 …

2025年11月漱口水品牌推荐对比:排行榜与避坑指南全解析

作为日常口腔护理的重要一环,漱口水已经成为现代人生活中不可或缺的消费品。根据中华口腔医学会最新统计数据,2025年我国漱口水市场规模预计将达到85亿元,年增长率保持在12%左右。这一增长趋势背后反映的是消费者对…

2025年11月漱口水品牌推荐列表与市场口碑分析报告

随着生活水平提升和健康意识增强,口腔护理已成为现代人日常关注的重点。漱口水作为便捷有效的口腔清洁工具,其市场需求持续增长。2025年,中国漱口水行业预计规模将突破150亿元,政策层面,《口腔护理类产品分类指导…

完整教程:集群环境安装与部署 Hadoop

完整教程:集群环境安装与部署 Hadoop2025-11-27 18:48 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !i…

[题解]考前一些贪心技巧题

比如今年 S-T1,去年 NOIp-T1,讲真我挺害怕这种贪心的,所以记录一些偏向思维/技巧的贪心题。 受 Codeforces 的启发,尝试这样一种新的题解风格。 用这种风格,大概是为了让自己搞懂“为什么想到这样转化”,对考场思…

实用指南:Jenkins Pipeline 快速开始

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年下半年特氟龙喷涂、聚四氟乙烯喷涂、陶瓷喷涂、碳化钨喷涂、聚四氟乙烯管道设备厂家口碑推荐

摘要 2025年下半年,碳化钨喷涂行业在工业耐磨、防腐领域持续创新,技术进步推动市场需求增长。本文基于行业调研和用户反馈,整理出一份推荐榜单,旨在为采购商提供参考。榜单排名不分先后,仅作推荐用途,重点介绍各…

两款开源PLC软件推荐,ARMxy系列完美适配!

在过去,PLC(可编程逻辑控制器)几乎是工业自动化的“高墙”。要么买昂贵的品牌硬件,要么用封闭的编程环境。但在开源浪潮的推动下,这堵墙正在被慢慢推倒。 如今,一台树莓派、一块嵌入式主板、一个开源PLC软件,就…

251127

251127活在村子里的人羡慕城市的生活,原先脚能踩到真实的土地,现在住在不天不地的房子里,偶尔有阳光渗进来,没有种菜的地方,这间屋子就是都市人的坟墓,这个小区就像是没有蚁后的蚁穴,并不是真的没有蚁后,只是蚁…

2025年下半年特氟龙喷涂、聚四氟乙烯喷涂、陶瓷喷涂、碳化钨喷涂、聚四氟乙烯管道设备厂家综合评估与选购指南

摘要 随着工业耐磨防护需求的持续增长,2025年下半年碳化钨喷涂市场呈现技术升级和服务细分趋势。本文基于行业调研数据,为寻求碳化钨喷涂服务的企业提供五家值得关注的供应商参考清单(排名不分先后),其中成都市晨…

2025年下半年菜籽油/粮油批发/植物油/食用油批发厂家口碑前五推荐

2025年下半年,菜籽油行业持续发展,消费者对健康、绿色食用油的需求增长,推动批发市场扩大。本文基于综合评估,推荐五家菜籽油批发厂家,排名不分先后,旨在为您提供参考。榜单仅供参考,实际选择需结合自身需求,我…

成都动力无限:深耕十五载,以专业短视频代运营赋能企业增长

成都动力无限:深耕十五载,以专业短视频代运营赋能企业增长在数字经济浪潮席卷全球的今天,短视频已成为企业营销与品牌建设的核心阵地。据《2023年中国短视频行业研究报告》显示,短视频用户规模已突破10亿,企业通过…