当前位置: 首页 > news >正文

Java NIO

IO 模型

IO指的是计算机与外部设备间交换数据的过程。比如磁盘,网络IO。
应用程序的IO分为两步:IO调用和IO执行。IO调用由应用程序发起,调用操作系统的 API,IO执行由操作系统内核执行。因为操作系统负责计算机资源的管理,不允许应用程序直接操纵。
进程的内存空间分为用户空间和内核空间。内核执行IO,等待IO设备准备好数据放入内核空间,之后将数据从内核空间拷贝到用户空间。

阻塞IO模型:
应用线程发起IO调用后,一直阻塞,直到内核将数据拷贝到用户空间为止。JAVA BIO 就是阻塞IO。
它的问题是:用户线程阻塞,为了并发执行多个IO,需要一个线程池管理IO线程。线程的问题是:占用内存资源多,线程上下文切换开销大,创建和销毁线程成本高。

非阻塞IO模型:
应用线程发起IO调用,立即返回结果(数据未就绪返回错误结果),不阻塞,称为非阻塞IO。这里的非阻塞是等待阶段不阻塞,操作系统内核将数据从内核空间拷贝到用户空间,应用线程仍然是阻塞的。
它的问题是:应用线程频繁轮询,消耗大量 CPU 资源。

IO多路复用模型:
应用线程不主动轮询,而是等待内核准备好数据后主动通知应用线程。
文件描述符:程序打开一个文件或者创建新文件,内核向进程返回一个文件描述符。
系统提供的函数(select, poll, epoll)同时监控多个文件描述符,任何一个返回内核数据就绪,通知应用线程读取数据。

信号驱动模型:
应用线程向内核发送信号,内核数据就绪后,向应用线程发送信号。应用线程读取数据。

异步IO:
上面四个IO,应用线程读取数据(将数据从内核空间拷贝到用户空间)都是阻塞的。
异步IO,应用线程发起IO调用,立即返回结果。内核将数据拷贝到用户空间后,发送信号通知应用线程。

NIO

NIO(non-blockiong IO)是同步非阻塞IO。它的核心概念有三个:channel, buffer, selector.底层是IO多路复用模型。
它与 BIO 的区别是:

  1. NIO 面向缓冲区,BIO 面向流。
  2. NIO 是非阻塞的,BIO 是阻塞的。

阻塞和非阻塞强调程序在等待调用结果(消息,返回值)时的状态。
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 对于同步调用来说,很多时候当前线程还是激活的状态,只是从逻辑上当前函数没有返回而已,即同步等待时什么都不干,白白占用着资源。

同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)。
同步,就是在发出一个"调用"时,在没有得到结果之前,该“调用”就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由“调用者”主动等待这个“调用”的结果。
而异步则是相反,"调用"在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在"调用"发出后,"被调用者"通过状态、通知来通知调用者,或通过回调函数处理这个调用

Channel

channel 类似BIO的流,channel 是双向的。

buffer

buffer 是数据块,缓存数据,用户线程可以读取/修改 buffer 任意位置的数据。

selector

一个 channel 代表一个连接,selector 利用IO多路复用模型,用一个 selector 线程注册,监听多个 channel。减少多个线程各自处理 channel 的线程池开销。

Selector

一个程序可能要建立多个连接,如果为每个 channel 分配一个线程。大部分时间线程处于阻塞状态,浪费资源。
因此用一个 selector 线程管理多个 channel,channel 以事件注册到 selector。selector 单线程轮询检测事件,如果事件就绪,交给处理器处理。
selector 可以并发处理成百上千个客户端连接。

NIO 简化为四种IO事件:
可读 SelectionKey.OP_READ
可写 SelectionKey.OP_WRITE
连接 SelectionKey.OP_CONNECT
接收 SelectionKey.OP_ACCEPT

Reactor 模型

Reactor 模型也基于事件驱动的IO多路复用。分为:reactor 线程和 handler 处理器。
reactor 线程建立连接,监听IO事件,执行IO读写,分发到 handlers 处理业务。

单线程模型:
reactor 和 处理器共用一个线程,优点是逻辑简单,缺点是:
线程数量少,性能差。时间长的事件会阻塞其他事件。

多线程模型:
处理器交给线程池。reactor 单线程执行建立连接,监听IO事件,执行IO读写。
线程池使得 handler 非阻塞处理业务。缺点是 reactor 单线程处理IO事件,无法处理大量新连接,IO就绪事件。

主从多线程模型:
reactor 线程分为主从线程。主 reactor 线程只负责建立连接。从 reactor 线程负责监听/处理IO事件。从 reactor 也可以使用线程池。

Netty

NIO 没有屏蔽平台差异,且因此建议使用NIO 框架,比如 netty。

http://www.dtcms.com/a/317577.html

相关文章:

  • 从 LinkedIn 到 Apache:Kafka 的架构设计与应用场景
  • 【25-cv-08899/08985】Lisa Audit 23张版权画作暴雷,Keith律所双案并发冻结跨境店铺!
  • Numpy科学计算与数据分析:Numpy入门之多平台安装与基础环境配置
  • Python 自动化与 Web 应用开发详细教案
  • 前端全栈修炼手册:从 Vue3 到工程化的进阶之路
  • Ethereum: 深入Hardhat Console, 我们的智能合约瑞士军刀
  • 微型导轨:智能家居抽屉的智能化应用
  • Text2SQL 智能问答系统开发-spider验证集(三)
  • 线程互斥与同步
  • C语言控制语句练习题1
  • 汽车以太网通信协议——SOME/IP
  • JTAG-SVF文件完整教程
  • 身份证实名认证接口增强联网平台的便利性与安全性
  • Centos上安装Mysql5.7教程
  • 智能提示词引擎的革新与应用:PromptPilot使用全解析
  • Bug 记录:SecureRandom.getInstanceStrong()导致验证码获取阻塞
  • 算法238. 除自身以外数组的乘积
  • 完整的登陆学生管理系统(配置数据库)
  • VSCode git提交记录中文commit显示乱码
  • 碰撞问题的分析
  • OpenAI开源大模型gpt-oss系列深度解析:从120B生产级到20B桌面级应用指南
  • C++实现线程池(3)缓存线程池
  • get请求中文字符参数乱码问题
  • 互联网一线大厂Java面试八股文整理(1000题附答案)
  • MATLAB深度学习之数据集-数据库构建方法详解
  • Leetcode——209. 长度最小的子数组
  • Redis中间件(二):Redis协议与异步方式
  • 用docker的方式快速搭建一个Hive的调测环境
  • Java 字节码文件(.class)的组成详解
  • 具有柔性关节的机械臂matlab仿真