【面试题精讲】javaIO模型之NIO

简介: 【面试题精讲】javaIO模型之NIO

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

首发博客地址

面试题手册

系列文章地址


1. 什么是NIO?

NIO(New I/O)是Java提供的一种非阻塞I/O模型,它在JDK 1.4中引入。与传统的I/O模型相比,NIO提供了更高效、更灵活的I/O操作方式。

2. 为什么需要NIO?

传统的I/O模型使用阻塞式I/O,在进行读写操作时会导致线程被阻塞,直到数据准备好或者写入完成。这种模型对于并发处理能力较弱,当有大量连接同时请求时,每个连接都需要一个独立的线程来处理,造成资源浪费和性能下降。

而NIO采用了事件驱动的方式,通过Selector轮询注册的通道,只有在通道真正有读写事件发生时才会进行处理,避免了线程被阻塞的情况,提高了系统的并发处理能力。

3. NIO的实现原理?

NIO的核心组件包括:Channel、Buffer和Selector。

  • Channel: 类似于传统I/O中的流,可以通过Channel进行数据的读取和写入。常见的Channel类型有SocketChannel、ServerSocketChannel、FileChannel等。
  • Buffer: 缓冲区,用于存储数据。在NIO中,所有的数据都是通过Buffer进行读写的。常见的Buffer类型有ByteBuffer、CharBuffer、IntBuffer等。
  • Selector: 选择器,用于监听多个Channel的事件。通过Selector可以实现单线程处理多个通道的读写操作。

NIO的工作原理如下:

  1. 创建一个Selector,并将其注册到需要监听的Channel上。
  2. 当有数据准备好时,Selector会轮询已注册的Channel,发现有事件发生的Channel后进行处理。
  3. 根据不同的事件类型(读、写、连接、接收),使用对应的方法进行处理。

4. NIO的使用示例

以下是一个简单的NIO服务器示例,用于接收客户端发送的消息并返回相同的消息给客户端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NIOServer {
    public static void main(String[] args) throws IOException {
        // 创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));
        serverSocketChannel.configureBlocking(false);
        // 创建Selector
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            // 阻塞等待就绪的Channel
            int readyChannels = selector.select();
            if (readyChannels == 0) {
                continue;
            }
            // 获取就绪的SelectionKey集合
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    // 接收新的连接
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    // 读取数据
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = socketChannel.read(buffer);
                    if (bytesRead > 0) {
                        buffer.flip();
                        byte[] data = new byte[buffer.remaining()];
                        buffer.get(data);
                        String message = new String(data, "UTF-8");
                        System.out.println("Received message: " + message);
                        // 返回相同的消息给客户端
                        ByteBuffer responseBuffer = ByteBuffer.wrap(data);
                        socketChannel.write(responseBuffer);
                    } else if (bytesRead < 0) {
                        // 客户端关闭连接
                        socketChannel.close();
                    }
                }
                // 移除处理过的SelectionKey
                keyIterator.remove();
            }
        }
    }
}

5. NIO的优点

  • 高并发性:NIO采用了事件驱动的方式,可以使用单线程处理多个通道的读写操作,提高系统的并发处理能力。
  • 非阻塞式I/O:NIO模型中的通道是非阻塞的,不会因为某个通道的读写操作而导致线程被阻塞,提高了系统的响应速度和吞吐量。
  • 内存管理优化:NIO使用了直接内存缓冲区,可以减少数据在Java堆和操作系统之间的拷贝次数,提高了I/O性能。

6. NIO的缺点

  • 复杂性较高:相比传统的阻塞式I/O模型,NIO的编程模型更加复杂,需要处理事件驱动、多路复用等概念。
  • 对编程人员要求较高:由于NIO的复杂性,对编程人员的技术要求较高,需要熟悉NIO相关的API和底层原理。

7. NIO的使用注意事项

  • 需要合理设置缓冲区大小:过小的缓冲区可能导致频繁的读写操作,影响性能;过大的缓冲区可能造成资源浪费。
  • 注意正确释放资源:在使用完Channel和Buffer后,需要及时关闭并释放资源,避免出现资源泄露问题。
  • 谨慎处理异常情况:NIO中的异常处理相对复杂,需要仔细处理各种异常情况,以保证程序的稳定性和可靠性。

8. 总结

NIO是一种非阻塞I/O模型,通过事件驱动和选择器机制实现高效的I/O操作。它具有高并发性、非阻塞式I/O和内存管理优化等优点,但也存在复杂性较高和对编程人员要求较高的缺点。在使用NIO时需要注意合理设置缓冲区大小、正确释放资源和谨慎处理异常情况。

本文由 mdnice 多平台发布

相关文章
|
16天前
|
Java 视频直播 数据库连接
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
20 2
|
4天前
|
存储 监控 Java
深入探索Java BIO与NIO输入输出模型:基于文件复制和socket通信
深入探索Java BIO与NIO输入输出模型:基于文件复制和socket通信
|
2月前
|
消息中间件 监控 Java
滴滴面试:谈谈你对Netty线程模型的理解?
Netty 线程模型是指 Netty 框架为了提供高性能、高并发的网络通信,而设计的管理和利用线程的策略和机制。 **Netty 线程模型被称为 Reactor(响应式)模型/模式,它是基于 NIO 多路复用模型的一种升级,它的核心思想是将 IO 事件和业务处理进行分离,使用一个或多个线程来执行任务的一种机制。** ## 1.**Reactor三大组件** Reactor 包含以下三大组件: ![image.png](https://cdn.nlark.com/yuque/0/2024/png/92791/1717079218890-89000a00-48bc-4a1a-b87e-e1b6
32 2
|
2月前
|
微服务 中间件 Nacos
01.【微服务架构】服务注册与发现:AP和CP,你选哪个?-- 面试准备+基本模型
【5月更文挑战第2天】面试准备应涵盖公司所使用的注册中心类型及其优缺点,了解其集群规模、QPS和机器性能。准备故障排查及优化案例。若公司未采用微服务,可熟悉ZooKeeper、Nacos或etcd的基本特性以讨论注册中心概念。面试时,可将话题引导至服务注册与发现,如被问及特定中间件,阐述为何选择它并讨论优缺点。当涉及微服务高可用性时,可强调服务注册与发现的作用。基础模型部分,需解释服务上线和下线流程,提及注册数据和分组功能,并举例说明。最后,简述服务注册与发现的高可用挑战。
41 8
|
2月前
|
设计模式 Oracle Java
阿里面试:NIO为什么会导致CPU100%?
在 Java 中总共有三种 IO 类型:BIO(Blocking I/O,阻塞I/O)、NIO(Non-blocking I/O,非阻塞I/O)和 AIO(Asynchronous I/O,异步I/O),它们的区别如下: 1. 在 JDK 1.4 之前,只有 BIO 一种模式,其开发过程相对简单,新来一个连接就会创建一个新的线程处理,但随着请求并发度的提升,BIO 很快遇到了性能瓶颈。 2. 所以在 JDK 1.4 以后开始引入了 NIO 技术,NIO 可以在一个线程中处理多个 IO 操作,提高了资源的利用率和系统的吞吐量。 3. 而到了 JDK 1.7 发布了 AIO 模型,它可以实现当线
43 0
|
2月前
|
数据可视化 Python
Python模型评估与选择:面试必备知识点
【4月更文挑战第17天】本文深入探讨了Python模型评估与选择在面试中的关键点,包括性能度量、过拟合与欠拟合识别、模型比较与选择、模型融合和偏差-方差权衡。强调了避免混淆评估指标、忽视模型验证和盲目追求高复杂度模型的常见错误,并提供相关代码示例,如交叉验证、网格搜索和超参数调优。通过理解这些概念和技巧,可在面试中展示出色的数据科学能力。
56 12
|
2月前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
2月前
|
监控 负载均衡 API
Python模型部署与服务化:面试中的热门话题
【4月更文挑战第17天】本文探讨了Python模型部署与服务化的面试重点,包括模型导出、API设计、服务化平台、性能优化、安全与合规等方面。强调了Flask、FastAPI等本地部署,以及阿里云、AWS等云服务部署。易错点涉及环境差异、服务稳定性和版本管理。提供Flask部署模型服务和阿里云SLS日志服务监控的代码示例,建议面试者全面掌握相关知识和实践经验。
41 9
|
2月前
|
调度 Python
Python并发编程模型:面试中的重点考察点
【4月更文挑战第14天】Python并发编程包括多线程、多进程和协程,常用于提高系统响应和资源利用率。多线程简单但受限于GIL;多进程可规避GIL,但通信开销大;协程适合IO密集型任务,学习成本较高。面试常见问题涉及并发并行概念、GIL影响、进程间通信同步及协程的异步IO理解。掌握并发模型的选择与应用,能有效提升面试表现。
36 0
动态规划|【斐波那契数列模型 】|面试题08.01三步问题
动态规划|【斐波那契数列模型 】|面试题08.01三步问题