BIO、NIO、AIO详解

一、基础概念: 阻塞/非阻塞、同步/异步

1.1 阻塞/非阻塞和同步/异步这两个概念的区别

1.1.1 他们不是一回事,是两个不同维度

概念 讨论的层面 问题核心
阻塞/非阻塞 线程等待状态 当线程发起I/O操作时,是"停下来等结果",还是"立刻返回自己干别的"
同步/异步 结果通知方式 谁负责通知I/O操作完成?是自己主动去取,还是系统回调告诉你

可以这么理解:

  • "阻塞/非阻塞"->线程等不等
  • "同步/异步"->结果谁来告诉你

两者的本质区别总结一句话: "阻塞/非阻塞"关注的是线程是否空等,"同步/异步"关注的是I/O完成后通知的方式。

1.1.2 一个生活例子: 点外卖 🍔

我们用"点外卖"的例子讲这四种组合:
①同步阻塞(最传统的方式)

你打电话点外卖 → 然后就在家门口等着,直到外卖送到,什么都不干。

  • 线程: 等待中(被阻塞)
  • 结果通知: 靠你自己等
  • 举例: Java的BIO模型
java 复制代码
# 类比
read() // 没数据?我就一直等...

②同步非阻塞

你打电话点外卖 → 然后每隔一会儿跑去门口看看外卖到了没。

  • 线程: 没有被阻塞(可以做别的事)
  • 结果通知: 仍然是你自己反复检查
  • 举例: Java 的 NIO(Selector 轮询)
java 复制代码
# 类比
while(true){
    if(channel.read(buffer) > 0){ 
        // 终于有数据了!
    } else {
        // 没有数据,继续干别的
    }
}

③异步阻塞(理论上存在但不常用)

你打电话点外卖 → 外卖系统说"到了我会打你电话",但你却一直拿着手机等电话(别的事也不做)。

  • 线程: 阻塞(在等通知)
  • 结果通知: 系统(外卖)回调告诉你
    实际系统中不常用

④异步非阻塞(最现代、最高效)

你打电话点外卖 → 系统登记好 → 你继续干别的,外卖送到后系统自动发短信通知你"到了"。

  • 线程: 不阻塞
  • 结果通知: 系统主动回调
  • 举例: Java AIO(异步通道回调 CompletionHandler)
java 复制代码
# 类比
channel.read(buffer, attachment, new CompletionHandler<Integer, Object>() {
    @Override
    public void completed(Integer result, Object attachment) {
        // 有数据可读了!系统通知我来处理
    }
});

二、三种I/O模型概述

2.1 BIO(同步阻塞IO)

BIO(Blocking I/O):指的是当线程执行 I/O 操作时,如果数据没准备好,就会一直等待,直到数据可用或发生异常才返回。

在 Java 网络编程中,BIO 典型表现就是:

一个连接对应一个线程,读写操作会阻塞线程。

2.2 NIO(同步非阻塞IO/多路复用IO)

目的是:让一个线程能同时管理多个连接,实现高并发的网络通信。

与BIO的明显区别是,发起第一次请求后,线程并没有被阻塞,它反复检查数据是否准备好,把原来大块不能用的阻塞时间分成了许多"小阻塞"(检查),所以进程不断有机会被执行。这个检查有没有准备好数据的过程有点类似于"轮询"。
核心组件:

  • Channel:类似传统 I/O 的流,但支持非阻塞操作
  • Buffer:用于数据的读写中转
  • Selector(选择器):核心机制,将多个 Channel 注册到一个 Selector 上,由它监控这些通道的 I/O 事件



IO多路复用

NIO 是上层 API 框架,是 Java 对这种能力的封装;NIO 的 Selector 就是"多路复用器",本质上就是在调用 select / epoll。

  • select: 注册事件由数组管理, 数组是有长度的, 32位机上限1024, 64位机上限2048。轮询查找时需要遍历数组。
  • poll:把select的数组采用链表实现,因此没了最大数量的限制
  • epoll方式:基于事件回调机制,回调时直接通知进程,无须使用某种方式来查看状态。

2.3 AIO(异步非阻塞IO)

核心思想: 应用线程发起 I/O 操作后立即返回,由操作系统在操作完成时自动通知应用(回调)。

也就是说:

线程发起 I/O 请求后不用自己轮询、也不会阻塞,当数据准备好(或者写完)时,系统会调用回调函数 CompletionHandler 来处理结果。

相关推荐
Arva .2 小时前
Spring Boot 配置文件
java·spring boot·后端
IT_Octopus2 小时前
https私人证书 PKIX path building failed 报错解决
java·spring boot·网络协议·https
程序员清风3 小时前
网易三面:Java中默认使用的垃圾回收器及特点分版本说说?
java·后端·面试
这周也會开心3 小时前
本地部署javaweb项目到Tomcat的三种方法
java·tomcat
小蒜学长3 小时前
jsp基于JavaWeb的原色蛋糕商城的设计与实现(代码+数据库+LW)
java·开发语言·数据库·spring boot·后端
摇滚侠3 小时前
Spring Boot中使用线程池来优化程序执行的效率!笔记01
java·spring boot·多线程
毕设源码-江学长3 小时前
计算机毕业设计java共享茶室预约微信小程序 微信小程序中的共享茶室预订平台 茶室共享预约小程序的设计与开发
java·微信小程序·课程设计
卡布奇诺-海晨4 小时前
2025版本的idea解决Git冲突
java·git·intellij-idea
Flash Dog4 小时前
【MyBatis】——执行过程
java·mybatis