说说 BIO、NIO、AIO

简介: 本文深入解析Web高并发下的I/O模型:BIO(阻塞)、NIO(非阻塞)与AIO(异步)。对比其原理与优劣,探讨多路复用机制如何提升性能,并介绍Java 21虚拟线程如何以BIO编码实现高性能,兼顾易用性与高并发。

问这个问题,通常是考察你对 Web 应用高并发的理解

预备知识

  • 开发 Web 应用,肯定分成客户端和服务器。
  • 客户端与服务器交互,肯定得做这么几件事:
  • 服务器线程等待有客户端连接上来
  • 客户端真的连上来了,建立连接
  • 客户端没有向服务器发送请求,此时服务器线程需要等待数据准备好
  • 客户端向服务器发送请求,需要将请求数据从网卡复制到系统内存
  • 上面 a. c. 这两个阶段,没有客户端连接,没有数据请求,这时是否需要一个线程时刻盯着?
  • 如果需要占用一个线程,那么就称线程被阻塞
  • 如果不需要线程盯着,线程可以腾出手来去干别的活,那么就称线程非阻塞
  • d. 阶段的数据复制,不会用到 CPU,也就是不会用到线程,同样也存在线程阻塞还是线程非阻塞两种情况

BIO(阻塞 I/O)

  • 是指 b. c. d.这几个阶段,线程都得阻塞,腾不出手干别的,即使此时它无所事事
  • 高并发下,阻塞线程多了,处理连接、处理请求的能力就会大受影响
  • 增加线程不可行,毕竟线程是有限资源,这是成本问题
  • 不增加线程也不行,没有新线程,没人去处理新连接,处理新请求

NIO(非阻塞 I/O)

  • 是指 b. c. 这两个阶段,线程可以不阻塞,腾出手干别的(怎么干别的,要靠多路复用)
  • 非阻塞 I/O 通常结合多路复用技术一起使用,能够在高并发下用少量线程处理大量请求
  • 多路复用是以面向事件的方式处理连接、处理请求,有事件发生才去处理,没有事件则不会占用线程
  • 使用了多路复用技术后,新客户端来了要连接,客户端发来了新请求,都会产生事件,把这些事件交给一个线程去统一处理就行了
  • 线程不会在高并发下存在无事可做的现象,它被充分压榨,利用率高

AIO(异步 I/O)

  • NIO 在 d. 这个阶段,线程仍需阻塞,不能被解放出来干其它活
  • AIO 则更进一步,只需要提前准备好回调函数,在数据复制时线程被解放,该干嘛干嘛,等数据复制完毕,由系统使用另外线程来调用回调函数做后续处理
  • AIO 在 Linux 下本质还是用多路复用技术来实现

小结

  • BIO 并发性低,但代码更容易编写
  • NIO 并发性高,不过代码编写困难
  • AIO 并发性在 Linux 下没有本质提高,用的人少
  • 【进阶】Java 21 起,正式支持虚拟线程
  • 配合虚拟线程时,仍然是以 BIO 方式来编写代码,代码编写容易
  • 虚拟线程非常廉价,线程不是不够吗,可劲加就行(不用担心线程闲置问题)
  • Java 21 重新实现了网络 API,虚拟线程底层也会配合多路复用机制,在代码易编写的情况下,兼具高性能

P.S.

  • B 是 Blocking 阻塞
  • N 是 Non-Blocking 非阻塞
  • A 是 Asynchronous 异步
相关文章
|
6月前
|
前端开发 Java 数据库
【数据载体POJO】POJO / DO / PO / DTO / VO / BO / Query / Entity / TO 全方位对比分析
本文系统解析Java企业级开发中各类数据载体(POJO/PO/DO/Entity/BO/DTO/TO/VO/Query)的本质、分层定位与使用边界,强调分层解耦、数据安全与职责单一原则,覆盖DDD、微服务及Spring生态实践,助力构建高内聚、低耦合的健壮架构。
|
9月前
|
监控 关系型数据库 MySQL
MySQL 联合索引
联合索引是MySQL中提升多列查询性能的关键技术,由多个列组成,遵循最左前缀原则。合理设计索引顺序可显著加速查询,避免全表扫描。需结合实际查询需求创建,避免冗余,配合EXPLAIN分析执行计划,优化数据库性能。(238字)
|
11月前
|
调度 Python
Python基于Fastapi与APScheduler的应用定时任务
基于FastAPI与APScheduler实现定时任务调度,通过lifespan管理生命周期,每分钟执行一次反馈任务,结合Uvicorn启动服务,构建高效异步任务处理系统。
704 3
HTTP协议中常见的状态码 ?
HTTP状态码分为1xx、2xx、3xx、4xx、5xx五类。常见状态码包括:101(切换协议,如WebSocket)、200(请求成功)、302(重定向)、401(未认证)、404(资源未找到)、500(服务器内部错误),广泛应用于Web开发中。
|
人工智能 缓存 JavaScript
SpringBoot 公共字段自动填充的6种方法
本文深入探讨了在Java开发中如何高效维护公共字段的多种解决方案。首先分析了手动设置公共字段带来的代码重复、维护成本高和易遗漏等问题,接着介绍了使用MyBatis-Plus自动填充、AOP统一处理等基础与进阶方案,实现字段自动赋值。文章还涵盖了多数据源适配、分布式ID生成、空指针防护、字段覆盖问题解决、性能优化以及操作日志追踪等生产环境中的最佳实践与避坑指南。最终通过方案组合使用,显著提升了开发效率与系统稳定性,为构建高质量企业级应用提供了有力支撑。
489 0
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
1489 60
|
存储 文件存储 数据库
对象存储、块存储、文件存储他们都有什么不通的作用?
对象存储、块存储、文件存储他们都有什么不通的作用?
2953 2
|
Java 数据库连接 mybatis
mybatis注解@Select中添加判断条件<script>
mybatis注解@Select中添加判断条件<script>
1538 0
|
JSON Dubbo Java
【Dubbo协议指南】揭秘高性能服务通信,选择最佳协议的终极攻略!
【8月更文挑战第24天】在分布式服务架构中,Apache Dubbo作为一款高性能的Java RPC框架,支持多种通信协议,包括Dubbo协议、HTTP协议及Hessian协议等。Dubbo协议是默认选择,采用NIO异步通讯,适用于高要求的内部服务通信。HTTP协议通用性强,利于跨语言调用;Hessian协议则在数据传输效率上有优势。选择合适协议需综合考虑性能需求、序列化方式、网络环境及安全性等因素。通过合理配置,可实现服务性能最优化及系统可靠性提升。
661 3
|
C语言 Python
exit、quit、sys.exit、os._exit,这么多退出方式,它们之间有什么区别呢?
exit、quit、sys.exit、os._exit,这么多退出方式,它们之间有什么区别呢?
1126 0

热门文章

最新文章