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)使用最广泛,平衡了性能和复杂度。

相关推荐
傻乐u兔2 分钟前
C语言进阶————指针3
c语言·开发语言
老毛肚9 分钟前
手写mybatis
java·数据库·mybatis
两点王爷12 分钟前
Java基础面试题——【Java语言特性】
java·开发语言
choke23316 分钟前
[特殊字符] Python 文件与路径操作
java·前端·javascript
Swift社区20 分钟前
Gunicorn 与 Uvicorn 部署 Python 后端详解
开发语言·python·gunicorn
choke23321 分钟前
Python 基础语法精讲:数据类型、运算符与输入输出
java·linux·服务器
码农阿豪32 分钟前
Python Flask应用中文件处理与异常处理的实践指南
开发语言·python·flask
岁岁种桃花儿32 分钟前
CentOS7 彻底卸载所有JDK/JRE + 重新安装JDK8(实操完整版,解决kafka/jps报错)
java·开发语言·kafka
csbysj20201 小时前
AngularJS 模块
开发语言
独好紫罗兰1 小时前
对python的再认识-基于数据结构进行-a003-列表-排序
开发语言·数据结构·python