Reactor模式

1.简介

Reactor模式是一种设计模式,主要用于处理服务端的并发请求。它的核心思想是使用一个或多个输入源(如网络连接、文件等)来接收事件,并将这些事件分发给相应的处理器进行处理。Reactor模式通常用于网络服务器,以支持高并发的I/O操作。

Reactor模式的关键组件包括:

  1. Reactor:负责监听和分发事件,是事件循环的核心。
  2. Handlers:事件处理器,用于处理Reactor分发的事件。
  3. Acceptor:用于接受新的连接请求。
  4. Event Demultiplexer:用于等待多个I/O事件的发生,通常是一个I/O多路复用器。

2. Reactor模式的工作原理:

  1. 初始化:Reactor初始化,创建Event Demultiplexer,并注册相关的I/O事件。
  2. 事件循环:Reactor进入事件循环,等待Event Demultiplexer通知有事件发生。
  3. 事件通知:当Event Demultiplexer检测到I/O事件时,通知Reactor。
  4. 事件分发:Reactor根据事件类型,将事件分发给相应的Handlers进行处理。
  5. 事件处理:Handlers接收事件并进行处理,如读取数据、发送响应等。
  6. 新连接处理:如果有新的连接请求,Acceptor将接受连接,并创建新的Handlers来处理新的连接。

3. Java实现Reactor模式示例:

3.1 Server

以下是一个简化的Reactor模式实现示例,使用Java NIO库:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ReactorPatternExample {

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8080));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Reactor reactor = new Reactor(selector, executorService);

        System.out.println("Server is running...");
        reactor.run();
    }

    static class Reactor {
        private final Selector selector;
        private final ExecutorService executorService;

        public Reactor(Selector selector, ExecutorService executorService) {
            this.selector = selector;
            this.executorService = executorService;
        }

        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    selector.select();
                    Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
                    while (selectedKeys.hasNext()) {
                        SelectionKey key = selectedKeys.next();
                        selectedKeys.remove();
                        if (key.isAcceptable()) {
                            handleAccept(key);
                        } else if (key.isReadable()) {
                            handleRead(key);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void handleAccept(SelectionKey key) throws IOException {
            ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
            executorService.execute(new Handler(socketChannel));
        }

        private void handleRead(SelectionKey key) throws IOException {
            SocketChannel socketChannel = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int bytesRead = socketChannel.read(buffer);
            if (bytesRead > 0) {
                buffer.flip();
                // Process the read data here
                System.out.println("Received data from client: " + new String(buffer.array(), 0, bytesRead));
            }
        }
    }

    static class Handler implements Runnable {
        private final SocketChannel socketChannel;

        public Handler(SocketChannel socketChannel) {
            this.socketChannel = socketChannel;
        }

        @Override
        public void run() {
            // Handle the connection, e.g., read data, send response
            try {
                while (!socketChannel.finishConnect()) {
                    // Wait for the connection to be established
                }
                // Connection established, now read/write data
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这个示例中,Reactor类负责事件循环,监听新的连接请求和读取事件。当有新的连接请求时,它将创建一个新的Handler线程来处理连接。Handler实现了Runnable接口,可以在ExecutorService中执行,以处理具体的I/O操作。

请注意,这个示例是一个简化的版本,实际应用中可能需要更复杂的错误处理、连接管理、资源清理等逻辑。

3.2 Client

在Reactor模式中,客户端通常不需要实现Reactor模式本身,因为它主要负责发送请求并接收响应,而不是处理并发连接和事件分发。然而,客户端可以利用Java NIO库来实现非阻塞的通信。

以下是一个简单的客户端实现示例,它使用Java NIO库来连接到服务器并发送数据:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NioClientExample {

    public static void main(String[] args) {
        String host = "localhost";
        int port = 8080;

        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);

            // 连接到服务器
            if (socketChannel.connect(new InetSocketAddress(host, port))) {
                System.out.println("Connected to the server");
                sendMessage(socketChannel);
            } else {
                System.out.println("Attempting to connect...");
                while (!socketChannel.finishConnect()) {
                    // 等待连接完成
                }
                sendMessage(socketChannel);
            }

            // 关闭资源
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void sendMessage(SocketChannel socketChannel) throws IOException {
        String message = "Hello, server!";
        ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());

        while (buffer.hasRemaining()) {
            socketChannel.write(buffer);
        }

        System.out.println("Message sent to the server");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值