• 非阻塞式 I/O 模型的工作原理【NIO】-2


     优化上一篇文上的代码。

    1. import java.io.IOException;
    2. import java.net.InetSocketAddress;
    3. import java.nio.ByteBuffer;
    4. import java.nio.channels.*;
    5. import java.util.Iterator;
    6. import java.util.Set;
    7. public class NonBlockingServer {
    8. public static void main(String[] args) throws IOException {
    9. // 创建 Selector
    10. Selector selector = Selector.open();
    11. // 创建 ServerSocketChannel 并绑定端口
    12. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    13. serverSocketChannel.bind(new InetSocketAddress(8080));
    14. serverSocketChannel.configureBlocking(false);
    15. // 将 ServerSocketChannel 注册到 Selector 上,并指定监听事件为接受连接事件
    16. serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    17. System.out.println("Server started, listening on port 8080...");
    18. while (true) {
    19. // 阻塞等待事件发生
    20. selector.select();
    21. // 获取发生事件的 SelectionKey 集合
    22. Set<SelectionKey> selectedKeys = selector.selectedKeys();
    23. Iterator<SelectionKey> iterator = selectedKeys.iterator();
    24. // 遍历处理事件
    25. while (iterator.hasNext()) {
    26. SelectionKey key = iterator.next();
    27. iterator.remove();
    28. // 创建新线程处理事件
    29. new Thread(new EventHandler(key)).start();
    30. }
    31. }
    32. }
    33. // 处理事件的线程类
    34. static class EventHandler implements Runnable {
    35. private SelectionKey key;
    36. public EventHandler(SelectionKey key) {
    37. this.key = key;
    38. }
    39. @Override
    40. public void run() {
    41. try {
    42. // 处理接受连接事件
    43. if (key.isAcceptable()) {
    44. ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
    45. SocketChannel clientChannel = serverChannel.accept();
    46. clientChannel.configureBlocking(false);
    47. clientChannel.register(key.selector(), SelectionKey.OP_READ);
    48. System.out.println("Client connected: " + clientChannel.getRemoteAddress());
    49. }
    50. // 处理读事件
    51. if (key.isReadable()) {
    52. SocketChannel clientChannel = (SocketChannel) key.channel();
    53. ByteBuffer buffer = ByteBuffer.allocate(1024);
    54. int bytesRead = clientChannel.read(buffer);
    55. if (bytesRead != -1) {
    56. buffer.flip();
    57. byte[] bytes = new byte[buffer.remaining()];
    58. buffer.get(bytes);
    59. String message = new String(bytes);
    60. System.out.println("Received message from client: " + message);
    61. // 原样返回给客户端
    62. clientChannel.write(ByteBuffer.wrap(bytes));
    63. } else {
    64. // 客户端关闭连接
    65. key.cancel();
    66. clientChannel.close();
    67. System.out.println("Client disconnected: " + clientChannel.getRemoteAddress());
    68. }
    69. }
    70. } catch (IOException e) {
    71. e.printStackTrace();
    72. }
    73. }
    74. }
    75. }

    在这个优化后的代码中,我们将处理事件的逻辑封装在 EventHandler 类中,并在遍历处理事件时创建新的线程来处理每个事件。这样可以实现并发处理不同连接的读写事件,提高系统的并发处理能力。

  • 相关阅读:
    重温FPGA开发34
    selenium中出现 Other element would receive the click的解决方式
    初级前端面试题(一) 之 html/css/js
    RabbitMQ原理和架构图解(附6大工作模式)
    Spring In Action 5 学习笔记 chapter3之JDBCTemplate 与JPA简单比较
    Day12--自定义组件-渲染my-search组件的基本结构
    代码随想录算法训练营第day14|二叉树理论基础、二叉树递归遍历、二叉树迭代遍历
    Linux 时区设置
    Go 字符串处理:fmt.Sprintf与string.Builder的比较
    HTML+CSS静态网页设计:(房地产网站设计与实现6页)
  • 原文地址:https://blog.csdn.net/bareape/article/details/136316435