网络 I/O:单 Selector 多线程(单线程模型)

简介: 网络 I/O:单 Selector 多线程(单线程模型)

网络编程中,I/O模型的选择对于程序的性能和可扩展性至关重要。单 Selector 多线程(单线程模型)是一种常见的网络 I/O 模型,它利用单个 Selector 对象来监听多个 Socket 连接,并通过多线程来处理这些连接的读写操作。这种模型在处理大量并发连接时具有较好的性能表现,尤其适用于高并发、低延迟的网络应用。

单 Selector 多线程模型的核心是 Selector 对象,它能够监视多个 Socket 对象的状态变化,包括连接、数据到达等事件。通过在 Selector 上注册感兴趣的事件和对应的 Socket,程序可以在一个单独的线程中轮询 Selector,检查哪些事件已经发生并执行相应的操作。

下面是一个使用 Java 的 NIO(Non-blocking I/O)实现单 Selector 多线程模型的示例代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
public class SingleSelectorExample {
    private static final int PORT = 8080;
    private static final int THREAD_COUNT = 10;
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(PORT));
        serverSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        for (int i = 0; i < THREAD_COUNT; i++) {
            new WorkerThread(selector).start();
        }
        while (true) {
            try {
                int readyChannels = selector.select();
                if (readyChannels == 0) continue;
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel server = (ServerSocketChannel) key.channel();
                        SocketChannel client = server.accept();
                        client.configureBlocking(false);
                        client.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int bytesRead = client.read(buffer);
                        if (bytesRead > 0) {
                            // 处理接收到的数据...
                        } else if (bytesRead < 0) {
                            client.close();
                        } else {
                            // 数据读取完毕,重置 buffer 或进行其他处理...
                        }
                    } else if (key.isWritable()) {
                        // 处理可写状态...
                    }
                    keyIterator.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上述代码中,我们创建了一个 ServerSocketChannel 用于监听客户端的连接请求。通过将 ServerSocketChannel 的配置设置为非阻塞模式,我们可以在同一个线程中处理其他 I/O 事件。然后,我们打开一个 Selector 对象,并在其上注册了 ServerSocketChannel,监听 OP_ACCEPT 事件(新的连接请求)。

接下来,我们创建了多个 WorkerThread 线程,每个线程都会轮询 Selector。在主线程中,我们进入一个无限循环,轮询 Selector 并处理已就绪的通道。当有新的连接请求到来时,我们接受连接并将新 SocketChannel 注册到 Selector 上,监听 OP_READ 事件(数据可读)。

对于已注册的 SocketChannel,我们还需要处理 OP_READ 事件。当数据可读时,我们从 SocketChannel 读取数据到 ByteBuffer 中。如果读取到的字节数大于 0,说明有数据可读,我们可以处理这些数据。如果读取到的字节数为 0,表示对端已经关闭连接。如果读取过程中发生 IOException,我们关闭 SocketChannel。

此外,如果某个通道的 SelectionKey 还处于可写状态(OP_WRITE),我们也可以处理相应的写操作。

通过这种方式,单 Selector 多线程模型可以在一个单独的线程中高效地处理多个 Socket 连接的 I/O 事件。这种模型适用于高并发、低延迟的网络应用,能够充分利用多核处理器的性能,并且避免了多线程编程的复杂性。

需要注意的是,在实际应用中,可能还需要考虑其他问题,如连接的管理、线程池的配置、资源的释放等。此外,不同的编程语言和框架提供了不同的 I/O 模型和工具,选择适合自己应用场景的模型和工具也是非常重要的。

目录
打赏
0
1
1
0
19
分享
相关文章
计算机网络TCP/IP四层模型
本文介绍了TCP/IP模型的四层结构及其与OSI模型的对比。网络接口层负责物理网络接口,处理MAC地址和帧传输;网络层管理IP地址和路由选择,确保数据包准确送达;传输层提供端到端通信,支持可靠(TCP)或不可靠(UDP)传输;应用层直接面向用户,提供如HTTP、FTP等服务。此外,还详细描述了数据封装与解封装过程,以及两模型在层次划分上的差异。
416 13
计算机网络OSI七层模型
OSI模型分为七层,各层功能明确:物理层传输比特流,数据链路层负责帧传输,网络层处理数据包路由,传输层确保端到端可靠传输,会话层管理会话,表示层负责数据格式转换与加密,应用层提供网络服务。数据在传输中经过封装与解封装过程。OSI模型优点包括标准化、模块化和互操作性,但也存在复杂性高、效率较低及实用性不足的问题,在实际中TCP/IP模型更常用。
269 10
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV1,用于移动视觉应用的高效卷积神经网络
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV1,用于移动视觉应用的高效卷积神经网络
136 3
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV1,用于移动视觉应用的高效卷积神经网络
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV2,含模型详解和完整配置步骤
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV2,含模型详解和完整配置步骤
164 1
RT-DETR改进策略【模型轻量化】| 替换骨干网络为MoblieNetV2,含模型详解和完整配置步骤
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
306 0
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
Netty源码—3.Reactor线程模型二
本文主要介绍了NioEventLoop的执行总体框架、Reactor线程执行一次事件轮询、Reactor线程处理产生IO事件的Channel、Reactor线程处理任务队列之添加任务、Reactor线程处理任务队列之执行任务、NioEventLoop总结。
Netty源码—2.Reactor线程模型一
本文主要介绍了关于NioEventLoop的问题整理、理解Reactor线程模型主要分三部分、NioEventLoop的创建和NioEventLoop的启动。
基于昇腾用PyTorch实现CTR模型DIN(Deep interest Netwok)网络
本文详细讲解了如何在昇腾平台上使用PyTorch训练推荐系统中的经典模型DIN(Deep Interest Network)。主要内容包括:DIN网络的创新点与架构剖析、Activation Unit和Attention模块的实现、Amazon-book数据集的介绍与预处理、模型训练过程定义及性能评估。通过实战演示,利用Amazon-book数据集训练DIN模型,最终评估其点击率预测性能。文中还提供了代码示例,帮助读者更好地理解每个步骤的实现细节。
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
168 23
Redis的线程模型
Redis采用单线程模型确保操作的原子性,每次只执行一个操作,避免并发冲突。它通过MULTI/EXEC事务机制、Lua脚本和复合指令(如MSET、GETSET等)保证多个操作要么全成功,要么全失败,确保数据一致性。Redis事务在EXEC前失败则不执行任何操作,EXEC后失败不影响其他操作。Pipeline虽高效但不具备原子性,适合非热点时段的数据调整。Redis 7引入Function功能,支持函数复用,简化复杂业务逻辑。总结来说,Redis的单线程模型简单高效,适用于高并发场景,但仍需合理选择指令执行方式以发挥其性能优势。
114 6
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问