【面试】迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章快快珍藏在Java后端开发面试中IO模型是高频考点。很多同学分不清同步/异步、阻塞/非阻塞更搞不懂BIO、NIO、AIO的区别。今天我们就用实战代码从底层原理到具体实现彻底讲清楚这些概念。## 一、核心概念同步 vs 异步阻塞 vs 非阻塞首先我们要理解两个维度的概念-同步/异步关注的是消息通知机制。同步是调用方主动等待结果异步是被调用方主动通知结果。-阻塞/非阻塞关注的是调用方在等待结果时的状态。阻塞是调用方被挂起等待非阻塞是调用方可以继续做其他事。### 1. 同步阻塞最典型BIO用户线程发起IO请求后内核进行数据准备线程一直阻塞等待直到数据就绪并拷贝到用户空间。### 2. 同步非阻塞NIO的基础用户线程发起IO请求后立即返回但需要不断轮询检查数据是否就绪。### 3. 异步阻塞少见用户线程发起IO请求后等待被通知结果但通知机制是异步的。### 4. 异步非阻塞AIO用户线程发起IO请求后立即返回当数据就绪时内核主动通知线程处理。## 二、BIO同步阻塞IOBlocking I/OBIO是最传统的IO模型每个连接对应一个线程。### 实战代码BIO服务器javaimport java.io.*;import java.net.*;public class BioServer { public static void main(String[] args) throws IOException { // 创建ServerSocket监听8080端口 ServerSocket serverSocket new ServerSocket(8080); System.out.println(BIO Server started on port 8080); while (true) { // ★ 阻塞点1accept()会阻塞直到有客户端连接 Socket clientSocket serverSocket.accept(); System.out.println(Client connected: clientSocket.getInetAddress()); // ★ 每个连接创建一个新线程处理 new Thread(() - { try { // 获取输入输出流 BufferedReader in new BufferedReader( new InputStreamReader(clientSocket.getInputStream())); PrintWriter out new PrintWriter( clientSocket.getOutputStream(), true); String line; // ★ 阻塞点2readLine()会阻塞直到读取到数据 while ((line in.readLine()) ! null) { System.out.println(Received: line); out.println(Echo: line); // 回显数据 } } catch (IOException e) { e.printStackTrace(); } finally { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } }}BIO的缺点- 每个连接需要独立线程连接数多时资源消耗巨大- 线程上下文切换开销大- 适用于连接数少且固定的场景## 三、NIO同步非阻塞IONon-blocking I/ONIO使用多路复用器Selector管理多个通道一个线程可以处理多个连接。### 实战代码NIO服务器javaimport java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;import java.util.Set;public class NioServer { public static void main(String[] args) throws IOException { // 1. 创建Selector多路复用器 Selector selector Selector.open(); // 2. 创建ServerSocketChannel并配置为非阻塞 ServerSocketChannel serverChannel ServerSocketChannel.open(); serverChannel.configureBlocking(false); // ★ 关键设置为非阻塞 serverChannel.bind(new InetSocketAddress(8080)); // 3. 将ServerSocketChannel注册到Selector关注ACCEPT事件 serverChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println(NIO Server started on port 8080); while (true) { // ★ 阻塞等待就绪的事件但这是高效的阻塞 int readyChannels selector.select(); if (readyChannels 0) continue; // 获取就绪的事件集合 SetSelectionKey selectedKeys selector.selectedKeys(); IteratorSelectionKey keyIterator selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key keyIterator.next(); if (key.isAcceptable()) { // 处理新连接 ServerSocketChannel server (ServerSocketChannel) key.channel(); SocketChannel clientChannel server.accept(); clientChannel.configureBlocking(false); // 注册到Selector关注READ事件 clientChannel.register(selector, SelectionKey.OP_READ); System.out.println(New client connected); } else if (key.isReadable()) { // 处理可读事件 SocketChannel clientChannel (SocketChannel) key.channel(); ByteBuffer buffer ByteBuffer.allocate(1024); int bytesRead clientChannel.read(buffer); // ★ 非阻塞读 if (bytesRead 0) { buffer.flip(); byte[] data new byte[buffer.limit()]; buffer.get(data); String message new String(data); System.out.println(Received: message); // 回显数据 ByteBuffer writeBuffer ByteBuffer.wrap( (Echo: message).getBytes()); clientChannel.write(writeBuffer); // ★ 非阻塞写 } else if (bytesRead -1) { // 客户端关闭连接 key.cancel(); clientChannel.close(); } } // ★ 重要移除已处理的key防止重复处理 keyIterator.remove(); } } }}NIO的核心优势- 一个线程管理多个连接通过Selector- 非阻塞读写不会阻塞线程- 适用于连接数多、连接时间短的场景如聊天服务器## 四、AIO异步非阻塞IOAsynchronous I/OAIO是真正的异步IO发起IO操作后立即返回当操作完成时通过回调通知。### 实战代码AIO服务器Java 7javaimport java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;public class AioServer { public static void main(String[] args) throws IOException, InterruptedException { // 创建异步服务器通道 AsynchronousServerSocketChannel serverChannel AsynchronousServerSocketChannel.open(); serverChannel.bind(new InetSocketAddress(8080)); System.out.println(AIO Server started on port 8080); // ★ 异步接受连接注册CompletionHandler回调 serverChannel.accept(null, new CompletionHandlerAsynchronousSocketChannel, Void() { Override public void completed(AsynchronousSocketChannel clientChannel, Void attachment) { // 继续接受下一个连接递归调用 serverChannel.accept(null, this); // 处理客户端连接 ByteBuffer buffer ByteBuffer.allocate(1024); // ★ 异步读取数据注册CompletionHandler clientChannel.read(buffer, buffer, new CompletionHandlerInteger, ByteBuffer() { Override public void completed(Integer bytesRead, ByteBuffer attachment) { if (bytesRead 0) { attachment.flip(); byte[] data new byte[attachment.limit()]; attachment.get(data); String message new String(data); System.out.println(Received: message); // 异步写回数据 ByteBuffer writeBuffer ByteBuffer.wrap( (Echo: message).getBytes()); clientChannel.write(writeBuffer, null, new CompletionHandlerInteger, Void() { Override public void completed(Integer result, Void attachment) { System.out.println(Write completed); } Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); } } Override public void failed(Throwable exc, ByteBuffer attachment) { exc.printStackTrace(); } }); } Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); // 保持主线程运行 Thread.currentThread().join(); }}AIO的特点- 真正的异步IO无需轮询- 通过回调机制处理完成事件- 适用于连接数多、连接时间长的场景如文件服务器- 但实际应用中NIO更常用操作系统支持更好## 五、总结对比| 模型 | 同步/异步 | 阻塞/非阻塞 | 线程模型 | 适用场景 ||------|-----------|-------------|----------|----------|| BIO | 同步 | 阻塞 | 一个连接一个线程 | 连接数少、固定 || NIO | 同步 | 非阻塞 | 一个线程管理多连接 | 连接数多、短连接 || AIO | 异步 | 非阻塞 | 回调机制 | 连接数多、长连接 |面试重点1. BIO的accept()和read()是阻塞点NIO通过Selector实现多路复用2. NIO虽然是非阻塞但仍然是同步IO需要主动轮询/处理事件3. AIO才是真正的异步IO但实际项目中NIO更常用如Netty基于NIO4. 理解IO模型对设计高性能服务器至关重要实战建议- 简单应用用BIO如小型内网工具- 高并发网络应用首选NIO如Netty框架- 文件操作可以考虑AIO如大文件读写希望这篇文章能帮你彻底理解IO模型面试不再怕
企业数字化 ERP 产品动态
相关推荐
STDF-Viewer:5大核心功能助力半导体测试数据可视化分析 STDF-Viewer:5大核心功能助力半导体测试数据可视化分析 【免费下载链接】STDF-Viewer A free GUI tool to visualize STDF (semiconductor Standard Test Data Format) data files. 项目地址: https://gitcode.com/gh_mirrors/st/STDF-Viewer
面对海量半导体… · 2026/9/18 13:30:23
Tabee浏览器标签页管理工具终极指南:深度解析标签页定制与自动化规则引擎 Tabee浏览器标签页管理工具终极指南:深度解析标签页定制与自动化规则引擎 【免费下载链接】chrome-tab-modifier Take control of your tabs 项目地址: https://gitcode.com/gh_mirrors/ch/chrome-tab-modifier
在现代Web开发和多任务处理中,浏览… · 2026/9/11 13:05:53
重庆电工证在哪可以查千万别踩坑:怕考不过白交培训费的你该知道这些 重庆电工证在哪可以查千万别踩坑:怕考不过白交培训费的你该知道这些 怕考不过白交培训费?你不是一个人。每年都有大量考生因为选择了不靠谱的培训机构、报名方式混乱、甚至证书真假难辨而被坑。特别是在重庆,电工证报考渠道繁多, 重庆电工证在哪可以查… · 2026/11/15 14:23:56
灵宝去哪考电工证通过率揭秘:实操考试心里没底怕挂科? 灵宝去哪考电工证通过率揭秘:实操考试心里没底怕挂科? 实操考试心里没底怕挂科,这是很多准备考电工证的小伙伴的真实写照。尤其是像你这样,刚毕业的洛阳工程类学生,面对【灵宝去哪考电工证】这个问题,既想快点拿到证书上岗,又担心自己基础不扎实、实操… · 2026/11/15 14:23:56
离石考电工证培训地址通过率揭秘:别再交完钱考不过了 离石考电工证培训地址通过率揭秘:别再交完钱考不过了 怕考不过白交培训费?离石考电工证培训地址你真的了解吗?现在市面上的电工证培训班五花八门,价格高低不一,但通过率却参差不齐。如果你正在准备考电工证,又担心浪费钱、浪费时间,那你必须了解清楚这… · 2026/11/15 14:23:56
中山那里报名考电工证千万别踩坑怎么避开陷阱 中山那里报名考电工证千万别踩坑怎么避开陷阱 证书过期了不知道怎么复审延期,这个问题真的让人头疼,尤其是在中山地区,很多人在报考电工证时因为不了解流程、没选对地方,结果花了冤枉钱还拿不到证。 千万别踩坑… · 2026/11/15 14:23:56
常熟电工证哪里报考良心建议:外省证怎么转过来?老电工给你说清楚 常熟电工证哪里报考良心建议:外省证怎么转过来?老电工给你说清楚 之前考的证在外省能不能转过来?这个问题,我听太多了。很多人在外地打工、学习,或者换城市发展,手里攥着一张外省的电工证,却不知道能不能在常熟用。今天我就从 常熟电工证哪里报考… · 2026/11/15 14:22:56
长春初级电工证怎么考?通过率揭秘全在这里 长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50
国内电工证报考条件与考试时间 低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50
电工作业时如何断电?电子证书到底能不能全国通用? 电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50
长春初级电工证怎么考?通过率揭秘全在这里 长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50
国内电工证报考条件与考试时间 低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50
电工作业时如何断电?电子证书到底能不能全国通用? 电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 1:51:20
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 4:02:19
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 3:02:05