Java 入门指南:初识 Java NIO

NIO 的引入

在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。当一个线程执行一个 I/O 操作时,它会被阻塞直到操作完成。这种阻塞模型在处理多个并发连接时可能会导致性能瓶颈,因为需要为每个连接创建一个线程,而线程的创建和切换都是有开销的。

为了解决这个问题,在 Java1.4 版本引入了 NIO(New I/O or Non-Blocking I/O)java.nio。提供了一种基于缓冲区、选择器和非阻塞 IO 模型的 IO 处理方式。相比于之前的 BIO 模型,NIO 可以实现更高的并发、更低的延迟以及更少的资源消耗。

I/O 包和 NIO 已经很好地集成了,java.io 也已经以 NIO 为基础重新实现了,所以现在它可以利用 NIO 的一些特性。例如,java.io 包中的一些类包含以块的形式读写数据的方法,这使得即使在面向流的系统中,处理速度也会更快。

使用 NIO 并不一定意味着高性能,它的性能优势主要体现在高并发和高延迟的网络环境下。当连接数较少、并发程度较低或者网络传输速度较快时,NIO 的性能并不一定优于传统的 BIO 。

NIO 的组成部分

缓冲区(Buffer)
  • 定义:缓冲区是 Java NIO 中的一个核心概念,它是用于存储IO操作数据的一段连续区域。
  • 类型 :Java NIO 提供了多种类型的缓冲区,如 ByteBufferCharBufferIntBuffer 等,以适应不同的数据类型需求。
  • 属性:每个缓冲区都有四个重要的属性,分别是容量(Capacity)、位置(Position)、限制(Limit)和标记(Mark)。
  • 操作:缓冲区的读写操作会修改其位置和限制属性,以确保数据能够正确地进行传输和处理。
通道(Channel)
  • 定义:通道是 Java NIO 中网络通信和文件 IO 操作的抽象,类似于传统 IO 中的 Stream,但它更加灵活和高效。
  • 类型 :Java NIO 提供了多种类型的通道,如 FileChannel(用于文件读写操作)、DatagramChannel(用于 UDP 协议的网络通信)、SocketChannel(用于 TCP 协议的网络通信)和 ServerSocketChannel(用于监听 TCP 连接请求)。
  • 特点:通道可以与缓冲区结合使用,通过缓冲区直接在内存中进行数据的读写操作,从而避免了传统IO中的频繁磁盘访问。
选择器(Selector)
  • 定义:选择器是Java NIO中的一个重要组件,它允许一个线程同时监听多个通道上的IO事件。
  • 作用:通过选择器,可以实现单线程管理多个通道的方式,从而大大提高IO操作的并发性能。
  • 使用:在选择器的模型中,每个通道都会注册到一个选择器上,并且每个通道都有一个其唯一的选择键(SelectionKey)对象来代表这个通道。当通道上的IO事件发生时,选择器会通知相应的线程进行处理。

NIO 与 BIO 的差异

I/O 与 NIO 最重要的区别是数据打包和传输 的方式,I/O 以流的方式处理数据,而 NIO 以块(缓冲区)的方式处理数据

面向流的 I/O 一次处理一个字节数据: 一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的 I/O 通常相当慢。

面向块的 I/O 一次处理一个数据块,按块处理数据比按流处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

传统 I/O 使用 Socket 和 SeverSocket 进行网络传输,存在阻塞问题。NIO 提供了 ServerChannelServerSocketChannel,支持非阻塞网络传输,提高了并发处理能力。

BIO、NIO 与 AIO

BIO(Blocking I/O):采用阻塞式 I/O 模型,线程在执行 I/O 操作时被阻塞,无法处理其他任务,适用于连接数较少且稳定的场景。

NIO(New I/O 或 Non-blocking I/O):使用非阻塞 I/O 模型,线程在等待 I/O 时可执行其他任务,通过 Selector 监控多个 Channel 上的事件,提高性能和可伸缩性,适用于高并发场景。

AIO(Asynchronous I/O):采用异步 I/O 模型,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程,进一步提高了并发处理能力,适用于高吞吐量场景。

NIO 的优势

IO 操作主要在 文件IO网络IO 场景下应用。NIO 的优势之处主要体现在网络 IO 场景下。

NIO(New I/O)的设计目标是解决传统 I/O(BIO,Blocking I/O)在处理大量并发连接时的性能瓶颈。传统 I/O 在网络通信中主要使用阻塞式 I/O,为每个连接分配一个线程。当连接数量增加时,系统性能将受到严重影响,线程资源成为关键瓶颈。而 NIO 可以在单个线程中处理多个并发连接 ,从而在网络传输中显著提高性能

  1. NIO 支持非阻塞 I/O,这意味着在执行 I/O 操作时,线程不会被阻塞。这使得在网络传输中可以有效地管理大量并发连接(数千甚至数百万)。而在操作文件时,这个优势没有那么明显,因为文件读写通常不涉及大量并发操作。

  2. NIO 支持 I/O 多路复用 ,这意味着一个线程可以同时监视多个通道(如 Socket),并在 I/O 事件(如可读、可写)准备好时处理它们。这大大提高了网络传输中的性能,因为单个线程可以高效地管理多个并发连接。操作文件时这个优势也无法提现出来。

  3. NIO 提供了 ByteBuffer,可以高效地管理缓冲区。这在网络传输中很重要,因为数据通常是以字节流的形式传输。操作文件的时候,虽然也有缓冲区,但优势仍然不够明显。

相关推荐
0白露16 分钟前
Apifox Helper 与 Swagger3 区别
开发语言
Tanecious.1 小时前
机器视觉--python基础语法
开发语言·python
叠叠乐1 小时前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
战族狼魂2 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
Tttian6223 小时前
Python办公自动化(3)对Excel的操作
开发语言·python·excel
xyliiiiiL3 小时前
ZGC初步了解
java·jvm·算法
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch4 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
独好紫罗兰4 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
bobz9654 小时前
k8s 怎么提供虚拟机更好
后端