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,可以高效地管理缓冲区。这在网络传输中很重要,因为数据通常是以字节流的形式传输。操作文件的时候,虽然也有缓冲区,但优势仍然不够明显。

相关推荐
hopetomorrow9 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
郑祎亦19 分钟前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
不是二师兄的八戒19 分钟前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
小牛itbull19 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i28 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落30 分钟前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
爱编程的小生31 分钟前
Easyexcel(2-文件读取)
java·excel
本当迷ya32 分钟前
💖2025年不会Stream流被同事排挤了┭┮﹏┭┮(强烈建议实操)
后端·程序员
GIS瞧葩菜39 分钟前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
chnming198744 分钟前
STL关联式容器之set
开发语言·c++