【大厂面试题】说下 IO 多路复用?

简介: IO多路复用(Input/Output Multiplexing)是一种在单个线程中管理多个输入/输出通道的技术。它允许一个线程同时监听多个输入流(例如网络套接字、文件描述符等),并在有数据可读或可写时进行相应的处理,而不需要为每个通道创建一个独立的线程

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

1688444016860.jpg

1、什么是 IO 多路复用

==IO多路复用(Input/Output Multiplexing)是一种在单个线程中管理多个输入/输出通道的技术。它允许一个线程同时监听多个输入流(例如网络套接字、文件描述符等),并在有数据可读或可写时进行相应的处理,而不需要为每个通道创建一个独立的线程。==

常见的IO多路复用机制包括select、poll和epoll。这些机制通过将多个IO通道注册到一个事件管理器中,然后通过阻塞方式等待事件的发生。一旦有事件发生(如有数据可读或可写),线程就会被唤醒,然后可以针对具体的事件进行处理。

IO多路复用的优点是可以有效地管理大量的IO通道,减少线程的创建和销毁开销,提高系统的并发性能。它在网络编程中特别有用,可以用于实现高性能的服务器和客户端应用程序。

2、IO 多路复用的优缺点

IO多路复用的优点包括:

  1. 高效性:通过单个线程同时管理多个IO通道,减少了线程的创建和销毁开销,提高了系统的并发性能。
  2. 资源节约:相比每个通道创建一个独立的线程,IO多路复用可以使用更少的线程来处理大量的IO通道,节约了系统资源。
  3. 简化编程模型:使用IO多路复用可以将异步IO操作转换为同步的事件驱动模型,简化了编程逻辑和代码复杂度。
  4. 可扩展性:由于使用了事件驱动模型,IO多路复用可以轻松地扩展到更多的IO通道,而不需要修改大量的代码。

然而,IO多路复用也有一些缺点:

  1. 学习曲线较陡:相比于传统的多线程或多进程模型,IO多路复用的概念和使用方式可能需要一些学习和理解。
  2. 对编程模型的要求较高:使用IO多路复用需要合理地设计和处理事件驱动的逻辑,否则可能会导致代码复杂、难以维护。
  3. 不适用于CPU密集型任务:IO多路复用适用于IO密集型任务,而对于CPU密集型任务,使用多线程或多进程模型可能更为合适。

    3、IO 多路复用的应用场景

    IO多路复用在以下几个应用场景中非常常见和有用:

  4. 网络编程:在网络编程中,服务器通常需要同时处理多个客户端的连接请求和数据传输。使用IO多路复用可以轻松管理多个网络套接字,监听并处理可读或可写的事件。这种方式可以实现高并发的服务器,提高系统的性能和扩展性。

  5. 高性能服务器:对于需要处理大量并发连接的服务器,如聊天服务器、实时通信服务器、游戏服务器等,使用IO多路复用可以有效地管理和处理多个客户端连接,提高服务器的吞吐量和响应速度。

  6. 文件操作:在文件操作中,当需要同时读取或写入多个文件时,可以使用IO多路复用来监听文件描述符的可读或可写事件,从而避免使用多线程或多进程的方式,提高文件操作的效率。

  7. 定时器和事件调度:IO多路复用可以用于实现定时器和事件调度功能。通过将定时器和事件的触发时间注册到IO多路复用机制中,可以在特定的时间点触发相应的事件,执行相应的操作。

总的来说,IO多路复用适用于需要同时管理和处理多个IO通道的场景,特别是在需要高并发处理的网络编程和服务器应用中非常常见。它可以提高系统的性能和资源利用率,简化编程模型,并且具有良好的可扩展性。

4、IO 多路复用的原理

IO多路复用是一种高效的IO处理机制,其原理如下:

  1. 多路复用:多路复用是指通过一个线程同时监听多个IO事件的就绪状态。在传统的阻塞IO模型中,每个IO操作都需要一个独立的线程来处理,当有大量的IO操作时,会导致线程数量的增加,从而带来线程切换和上下文切换的开销。而多路复用通过使用一个线程来监听多个IO事件,避免了线程数量的增加,减少了线程切换和上下文切换的开销。

  2. IO事件就绪通知:多路复用机制通过操作系统提供的系统调用(如select、poll、epoll等)来监听多个IO事件的就绪状态。当有任何一个IO事件就绪时,操作系统会通知应用程序,告知哪些IO事件已经准备好可以进行读取或写入操作。

  3. 非阻塞IO:多路复用机制通常与非阻塞IO配合使用。在非阻塞IO模型中,当一个IO操作无法立即完成时,不会阻塞线程,而是立即返回一个错误码或特定的状态,应用程序可以继续处理其他IO操作或其他任务,提高了系统的并发性能。

  4. 事件循环:多路复用机制通过事件循环来处理就绪的IO事件。事件循环会不断地监听IO事件的就绪状态,当有IO事件就绪时,会调用相应的回调函数来处理该事件。通过事件循环的方式,可以高效地处理多个IO操作。

    5、IO 多路复用的实现

    IO多路复用的实现可以通过操作系统提供的不同系统调用来实现,其中最常用的有select、poll和epoll。

  5. select
    select是最古老的IO多路复用机制,它使用一个文件描述符集合来监听多个IO事件的就绪状态。应用程序需要将需要监听的文件描述符添加到集合中,然后调用select函数进行监听。当有文件描述符就绪时,select函数会返回,并告知哪些文件描述符已经准备好进行读取或写入操作。然后应用程序可以通过遍历文件描述符集合来处理就绪的IO事件。

  6. poll
    poll是select的改进版本,它也使用一个文件描述符集合来监听多个IO事件的就绪状态。与select不同的是,poll不需要每次调用都将文件描述符集合传递给内核,而是使用一个pollfd结构体数组来传递。应用程序需要将需要监听的文件描述符和事件类型添加到pollfd数组中,然后调用poll函数进行监听。当有文件描述符就绪时,poll函数会返回,并告知哪些文件描述符已经准备好进行读取或写入操作。然后应用程序可以通过遍历pollfd数组来处理就绪的IO事件。

  7. epoll
    epoll是Linux特有的IO多路复用机制,它使用一个内核事件表来管理和监听多个IO事件的就绪状态。应用程序需要将需要监听的文件描述符添加到内核事件表中,然后调用epoll_wait函数进行监听。当有文件描述符就绪时,epoll_wait函数会返回,并告知哪些文件描述符已经准备好进行读取或写入操作。与select和poll不同的是,epoll使用回调函数来处理就绪的IO事件,而不需要应用程序遍历事件列表。

6、用 Java 写一段 IO 多路复用的代码

package com.pany.camp.io;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @description:  IO多路复用
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-07-04 12:09
 */
public class IOMultiplexingExample {
   
   

    public static void main(String[] args) throws IOException {
   
   
        // 创建一个Selector
        Selector selector = Selector.open();

        // 创建需要监听的Channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress("localhost", 8080));
        serverSocketChannel.configureBlocking(false);

        // 将Channel注册到Selector,并指定监听事件为接收连接
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
   
   
            // 阻塞等待就绪的事件
            selector.select();

            // 获取就绪的事件集合
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

            // 处理就绪的事件
            while (keyIterator.hasNext()) {
   
   
                SelectionKey key = keyIterator.next();

                if (key.isAcceptable()) {
   
   
                    // 接收连接事件
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel clientChannel = serverChannel.accept();
                    clientChannel.configureBlocking(false);
                    clientChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
   
   
                    // 可读事件
                    SocketChannel clientChannel = (SocketChannel) key.channel();
                    // 读取数据
                    // ...
                }

                // 处理完事件后,需要从集合中移除该事件
                keyIterator.remove();
            }
        }
    }
}

将ServerSocketChannel注册到Selector上,监听接收连接事件。然后通过循环调用 selector.select() 来阻塞等待就绪的事件。一旦有事件就绪,就会进入事件处理的循环,根据事件类型进行相应的处理。处理完事件后,需要从集合中移除该事件。

需要注意的是,IO多路复用适用于非阻塞IO,因此需要将Channel设置为非阻塞模式。在实际应用中,可能还需要处理写入事件、连接事件等其他类型的事件。

1686494501743.jpg

💕💕 本文由激流原创,原创不易,感谢支持
💕💕喜欢的话记得点赞收藏啊
1687869804912.jpg

目录
相关文章
|
3月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
2月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
19天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
7天前
|
消息中间件 NoSQL Java
面试官:谈谈你对IO多路复用的理解?
面试官:谈谈你对IO多路复用的理解?
20 0
面试官:谈谈你对IO多路复用的理解?
|
8天前
|
网络协议 Java Linux
高并发编程必备知识IO多路复用技术select,poll讲解
高并发编程必备知识IO多路复用技术select,poll讲解
|
3月前
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。
|
3月前
|
缓存 网络协议 算法
【Linux系统编程】深入剖析:四大IO模型机制与应用(阻塞、非阻塞、多路复用、信号驱动IO 全解读)
在Linux环境下,主要存在四种IO模型,它们分别是阻塞IO(Blocking IO)、非阻塞IO(Non-blocking IO)、IO多路复用(I/O Multiplexing)和异步IO(Asynchronous IO)。下面我将逐一介绍这些模型的定义:
133 1
|
4月前
|
Linux C++
c++高级篇(三) ——Linux下IO多路复用之poll模型
c++高级篇(三) ——Linux下IO多路复用之poll模型
|
4月前
|
缓存 监控 网络协议
c++高级篇(二) ——Linux下IO多路复用之select模型
c++高级篇(二) ——Linux下IO多路复用之select模型
|
3月前
stm32f407探索者开发板(十四)——IO引脚复用和映射
stm32f407探索者开发板(十四)——IO引脚复用和映射
下一篇
无影云桌面