java BIO、NIO、AIO用法样例

1. BIO (Blocking I/O) - 同步阻塞 I/O

BIO 是传统的网络编程模型,每个连接对应一个线程,当线程执行读/写操作时会被阻塞,直到数据就绪。

示例:BIO 服务器

java 复制代码
import java.net.*;
import java.io.*;

public class BioServer {
   public static void main(String[] args) throws IOException {
       ServerSocket serverSocket = new ServerSocket(8080);
       System.out.println("BIO Server started on port 8080");

       while (true) {
           Socket clientSocket = serverSocket.accept(); // 阻塞等待客户端连接
           new Thread(() -> {
               try {
                   BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                   PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                   String request;
                   while ((request = in.readLine()) != null) { // 阻塞读取数据
                       System.out.println("Received: " + request);
                       out.println("Echo: " + request); // 响应客户端
                   }
                   clientSocket.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }).start();
       }
   }
}

特点

  • 每个连接一个线程,适合连接数少的场景。
  • 编程简单,但线程开销大,无法应对高并发。

2. NIO (Non-blocking I/O) - 同步非阻塞 I/O

NIO 基于 Channel 和 Selector,使用单个线程管理多个连接,通过事件驱动机制实现非阻塞。

示例:NIO 服务器

java 复制代码
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class NioServer {
  public static void main(String[] args) throws IOException {
      ServerSocketChannel serverChannel = ServerSocketChannel.open();
      serverChannel.bind(new InetSocketAddress(8080));
      serverChannel.configureBlocking(false); // 非阻塞模式
      Selector selector = Selector.open();
      serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册接受连接事件

      System.out.println("NIO Server started on port 8080");

      while (true) {
          selector.select(); // 阻塞直到有事件发生
          Set<SelectionKey> keys = selector.selectedKeys();
          Iterator<SelectionKey> iter = keys.iterator();

          while (iter.hasNext()) {
              SelectionKey key = iter.next();
              iter.remove();

              if (key.isAcceptable()) {
                  ServerSocketChannel server = (ServerSocketChannel) key.channel();
                  SocketChannel client = server.accept();
                  client.configureBlocking(false);
                  client.register(selector, SelectionKey.OP_READ); // 注册读事件
                  System.out.println("Client connected: " + client.getRemoteAddress());
              } else if (key.isReadable()) {
                  SocketChannel client = (SocketChannel) key.channel();
                  ByteBuffer buffer = ByteBuffer.allocate(1024);
                  int read = client.read(buffer); // 非阻塞读取
                  if (read > 0) {
                      buffer.flip();
                      byte[] data = new byte[buffer.remaining()];
                      buffer.get(data);
                      String request = new String(data);
                      System.out.println("Received: " + request);
                      
                      // 响应客户端
                      ByteBuffer response = ByteBuffer.wrap(("Echo: " + request).getBytes());
                      client.write(response);
                  } else if (read == -1) {
                      client.close();
                  }
              }
          }
      }
  }
}

特点

  • 单线程处理多连接,减少线程开销。
  • 复杂度较高,需要处理事件循环和缓冲区。

3. AIO (Asynchronous I/O) - 异步非阻塞 I/O

AIO 基于回调机制,应用程序发起 I/O 操作后立即返回,当操作完成时系统会通知应用程序。

示例:AIO 服务器

java 复制代码
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.concurrent.*;

public class AioServer {
 public static void main(String[] args) throws IOException {
     AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
     server.bind(new InetSocketAddress(8080));

     System.out.println("AIO Server started on port 8080");

     // 接受连接的回调
     server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
         @Override
         public void completed(AsynchronousSocketChannel client, Void attachment) {
             server.accept(null, this); // 继续接受下一个连接

             ByteBuffer buffer = ByteBuffer.allocate(1024);
             // 读取数据的回调
             client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                 @Override
                 public void completed(Integer bytesRead, ByteBuffer buffer) {
                     if (bytesRead > 0) {
                         buffer.flip();
                         byte[] data = new byte[buffer.remaining()];
                         buffer.get(data);
                         String request = new String(data);
                         System.out.println("Received: " + request);

                         // 响应客户端
                         ByteBuffer response = ByteBuffer.wrap(("Echo: " + request).getBytes());
                         client.write(response, null, new CompletionHandler<Integer, Void>() {
                             @Override
                             public void completed(Integer result, Void attachment) {
                                 try {
                                     client.close();
                                 } catch (IOException e) {
                                     e.printStackTrace();
                                 }
                             }
                             @Override
                             public void failed(Throwable exc, Void attachment) {
                                 exc.printStackTrace();
                             }
                         });
                     }
                 }
                 @Override
                 public void failed(Throwable exc, ByteBuffer attachment) {
                     exc.printStackTrace();
                 }
             });
         }
         @Override
         public void failed(Throwable exc, Void attachment) {
             exc.printStackTrace();
         }
     });

     // 保持服务器运行
     Thread.currentThread().join();
 }
}

特点

  • 完全异步,基于回调或 Future,性能高。
  • 编程模型复杂,适合连接数多且长连接的场景。

对比分析

特性 BIO NIO AIO
模型 同步阻塞 同步非阻塞(多路复用) 异步非阻塞
线程数 一个连接一个线程 一个线程处理多个连接 少量线程,回调驱动
吞吐量 低(线程上下文切换开销大) 中高
编程复杂度 简单 复杂(需处理 Selector 等) 非常复杂(回调地狱)
适用场景 连接数少、固定架构 连接数多、短连接(如聊天) 连接数多、长连接(如文件传输)
JDK 版本 Java 1.0+ Java 1.4+ Java 1.7+

总结

  • BIO:简单但性能差,适合低并发场景。
  • NIO:性能较好,复杂度高,适合高并发短连接(Netty 基于 NIO)。
  • AIO:性能最佳,但编程复杂,在 Linux 上优势不明显(Linux 对 AIO 支持有限,常用 NIO)。

实际项目中,NIO 框架(如 Netty)使用最广泛,平衡了性能和复杂度。

相关推荐
不绝1911 分钟前
C#进阶——内存
开发语言·c#
风送雨2 分钟前
Go 语言进阶学习:第 1 周 —— 并发编程深度掌握
开发语言·学习·golang
小白不想白a3 分钟前
RabbitMQ监控
java·rabbitmq·java-rabbitmq
小北方城市网4 分钟前
第 5 课:服务网格(Istio)实战|大规模微服务的流量与安全治理体系
大数据·开发语言·人工智能·python·安全·微服务·istio
jghhh015 分钟前
自适应信号时频处理方法MATLAB实现(适用于非线性非平稳信号)
开发语言·算法·matlab
AC赳赳老秦5 分钟前
Go语言微服务文档自动化生成:基于DeepSeek的智能解析实践
大数据·开发语言·人工智能·微服务·golang·自动化·deepseek
古城小栈5 分钟前
Rust 之 迭代器
开发语言·rust
r***12385 分钟前
GO 快速升级Go版本
开发语言·redis·golang
Overt0p7 分钟前
MQ简单介绍以及RabbitMQ基础使用,快速上手
java·分布式·rabbitmq
木木木一8 分钟前
Rust学习记录--C5 Rust struct
开发语言·学习·rust