ITPub博客

首页 > 应用开发 > Java > 使用 Java NIO 实现 Reactor 模型。

使用 Java NIO 实现 Reactor 模型。

原创 Java 作者:tiannuo 时间:2026-05-13 14:04:05 0 删除 编辑

Java NIO Reactor 示例代码

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.*;

import java.util.Iterator;

import java.util.Set;


public class NioReactorHttpServer {


    private static final int PORT = 8080;

    private static final int BUFFER_SIZE = 1024;


    public static void main(String[] args) throws IOException {

        // 1. 创建Selector

        Selector selector = Selector.open();


        // 2. 创建ServerSocketChannel

        ServerSocketChannel serverChannel = ServerSocketChannel.open();

        serverChannel.bind(new InetSocketAddress(PORT));

        serverChannel.configureBlocking(false);


        // 3. 注册Accept事件

        serverChannel.register(selector, SelectionKey.OP_ACCEPT);


        System.out.println("NIO Reactor HTTP Server started on port " + PORT);


        // 4. Reactor事件循环

        while (true) {

            selector.select(); // 阻塞等待事件

            Set<SelectionKey> keys = selector.selectedKeys();

            Iterator<SelectionKey> it = keys.iterator();


            while (it.hasNext()) {

                SelectionKey key = it.next();

                it.remove();


                try {

                    if (key.isAcceptable()) {

                        handleAccept(key, selector);

                    } else if (key.isReadable()) {

                        handleRead(key);

                    } else if (key.isWritable()) {

                        handleWrite(key);

                    }

                } catch (IOException e) {

                    key.cancel();

                    key.channel().close();

                    e.printStackTrace();

                }

            }

        }

    }


    private static void handleAccept(SelectionKey key, Selector selector) throws IOException {

        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();

        SocketChannel clientChannel = serverChannel.accept();

        clientChannel.configureBlocking(false);


        // 给客户端注册可读事件

        clientChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(BUFFER_SIZE));

        System.out.println("Accepted connection from " + clientChannel.getRemoteAddress());

    }


    private static void handleRead(SelectionKey key) throws IOException {

        SocketChannel channel = (SocketChannel) key.channel();

        ByteBuffer buffer = (ByteBuffer) key.attachment();

        int read = channel.read(buffer);


        if (read == -1) {

            channel.close();

            key.cancel();

            System.out.println("Client disconnected.");

            return;

        }


        String request = new String(buffer.array(), 0, buffer.position());

        if (request.contains("\r\n\r\n")) { // 请求头结束

            System.out.println("Received request:\n" + request);


            // 简单处理HTTP请求

            String body = "<html><body><h1>Hello NIO Reactor!</h1></body></html>";

            byte[] bodyBytes = body.getBytes();

            String response = "HTTP/1.1 200 OK\r\n" +

                    "Content-Length: " + bodyBytes.length + "\r\n" +

                    "Content-Type: text/html\r\n" +

                    "Connection: keep-alive\r\n" + // 支持长连接

                    "\r\n";


            ByteBuffer responseBuffer = ByteBuffer.allocate(response.getBytes().length + bodyBytes.length);

            responseBuffer.put(response.getBytes());

            responseBuffer.put(bodyBytes);

            responseBuffer.flip();


            // 改为可写事件

            key.interestOps(SelectionKey.OP_WRITE);

            key.attach(responseBuffer);

        }

    }


    private static void handleWrite(SelectionKey key) throws IOException {

        SocketChannel channel = (SocketChannel) key.channel();

        ByteBuffer buffer = (ByteBuffer) key.attachment();

        channel.write(buffer);


        if (!buffer.hasRemaining()) {

            // 写完了,切换回读模式,保持长连接

            buffer.clear();

            key.attach(ByteBuffer.allocate(BUFFER_SIZE));

            key.interestOps(SelectionKey.OP_READ);

        }

    }

}

核心说明

Selector + Channel

Selector 用于监听多个通道事件。

ServerSocketChannel 监听客户端连接。

SocketChannel 非阻塞模式。

事件循环

select() 阻塞等待事件。

遍历 selectedKeys() 处理事件。

非阻塞读写

读:channel.read(buffer)。

写:channel.write(buffer)。

使用 ByteBuffer 存储数据。

长连接处理

Connection: keep-alive。

写完响应后,保持通道注册 OP_READ,继续等待下一次请求。

并发高效

单线程 Reactor 可以同时处理成百上千连接。

可拓展多线程 Reactor,处理 CPU 密集型业务。

测试方法

curl -v --http1.1 http://localhost:8080

curl -v --http1.1 -H "Connection: keep-alive" http://localhost:8080


你会看到同一 TCP 连接可以发送多个请求,服务器继续响应。


https://vk.com/club238613049 https://vk.com/topic-238613049_61620133 https://vk.com/topic-238613049_61620133 https://vk.com/topic-238613049_61660416 https://vk.com/topic-238613049_61661015 https://vk.com/topic-238613049_61662370 https://vk.com/topic-238613049_61663127 https://vk.com/topic-238613049_61663727 https://vk.com/topic-238613049_61664344 https://vk.com/topic-238613049_61665403 https://vk.com/topic-238613049_61666396 https://vk.com/topic-238613049_61666859 https://vk.com/topic-238613049_61667466 https://vk.com/topic-238613049_61667973 https://vk.com/topic-238613049_61668424 https://vk.com/topic-238613049_61668843 https://vk.com/topic-238613049_61669431 https://vk.com/topic-238613049_61669923 https://vk.com/topic-238613049_61670528 https://vk.com/topic-238613049_61671056 https://vk.com/topic-238613049_61672040 https://vk.com/topic-238613049_61673949 https://vk.com/topic-238613049_61674520 https://vk.com/topic-238613049_61675099 https://vk.com/topic-238613049_61675713 https://vk.com/topic-238613049_61676862 https://vk.com/topic-238613049_61677472 https://vk.com/topic-238613049_61678068 https://vk.com/topic-238613049_61678633 https://vk.com/topic-238613049_61679471 https://vk.com/topic-238613049_61680104 https://vk.com/topic-238613049_61680977 https://vk.com/topic-238613049_61682733 https://vk.com/topic-238613049_61683900 https://vk.com/topic-238613049_61685288 https://vk.com/topic-238613049_61687400 https://vk.com/topic-238613049_61688091 https://vk.com/topic-238613049_61688892 https://vk.com/topic-238613049_61689625 https://vk.com/topic-238613049_61692163 https://vk.com/topic-238613049_61694912 https://vk.com/topic-238613049_61696022 https://vk.com/topic-238613049_61697404 https://vk.com/topic-238613049_61699759 https://vk.com/topic-238613049_61700290 https://vk.com/topic-238613049_61703158 https://vk.com/topic-238613049_61710898 https://vk.com/topic-238613049_61712349 https://vk.com/topic-238613049_61715121 https://vk.com/topic-238613049_61716645 https://vk.com/topic-238613049_61718235 https://vk.com/topic-238613049_61719514 https://vk.com/topic-238613049_61719966 https://vk.com/topic-238613049_61720951 https://vk.com/topic-238613049_61723091 https://vk.com/topic-238613049_61723610 https://vk.com/topic-238613049_61724095 https://vk.com/topic-238613049_61725830 https://vk.com/topic-238613049_61727910 https://vk.com/topic-238613049_61728369 https://vk.com/topic-238613049_61734596 https://vk.com/topic-238613049_61735204 https://vk.com/topic-238613049_61735918 https://vk.com/topic-238613049_61738211 https://vk.com/topic-238613049_61742986 https://vk.com/topic-238613049_61743758 https://vk.com/topic-238613049_61744456 https://vk.com/topic-238613049_61745154 https://vk.com/topic-238613049_61746305 https://vk.com/topic-238613049_61747520 https://vk.com/topic-238613049_61749937 https://vk.com/topic-238613049_61753913 https://vk.com/topic-238613049_61754322 https://vk.com/topic-238613049_61755170 https://vk.com/topic-238613049_61758587 https://vk.com/topic-238613049_61759748 https://vk.com/topic-238613049_61760124 https://vk.com/topic-238613049_61760703 https://vk.com/topic-238613049_61761029 https://vk.com/topic-238613049_61762073 https://vk.com/topic-238613049_61764542 https://vk.com/topic-238613049_61765991 https://vk.com/topic-238613049_61766666 https://vk.com/topic-238613049_61767428 https://vk.com/topic-238613049_61768459 https://vk.com/topic-238613049_61770494 https://vk.com/topic-238613049_61772768 https://vk.com/topic-238613049_61773220 https://vk.com/topic-238613049_61773366 https://vk.com/topic-238613049_61773872 https://vk.com/topic-238613049_61774188 https://vk.com/topic-238613049_61774912 https://vk.com/topic-238613049_61775489 https://vk.com/topic-238613049_61777185 https://vk.com/topic-238613049_61777359 https://vk.com/topic-238613049_61778096 https://vk.com/topic-238613049_61779337 https://vk.com/topic-238613049_61779962 https://vk.com/topic-238613049_61780146 https://vk.com/topic-238613049_61780848 https://vk.com/topic-238613049_61781349 https://vk.com/topic-238613049_61781714 https://vk.com/topic-238613049_61784007 https://vk.com/topic-238613049_61784224 https://vk.com/topic-238613049_61785616 https://vk.com/topic-238613049_61787896 https://vk.com/topic-238613049_61791261 https://vk.com/topic-238613049_61792829 https://vk.com/topic-238613049_61796205 https://vk.com/topic-238613049_61796572 https://vk.com/topic-238613049_61797600 https://vk.com/topic-238613049_61798992 https://vk.com/topic-238613049_61799871 https://vk.com/topic-238613049_61800137 https://vk.com/topic-238613049_61800423 https://vk.com/topic-238613049_61802707 https://vk.com/topic-238613049_61803481 https://vk.com/topic-238613049_61805679 https://vk.com/topic-238613049_61811434

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050070/viewspace-3117738/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-05-08

  • 博文量
    74
  • 访问量
    66696