18.1.5 Java IO/NIO/AIO对比分析

1. IO模型基础概念

1.1 IO模型分类

  • BIO (Blocking IO):同步阻塞IO,传统的Java IO
  • NIO (Non-blocking IO):同步非阻塞IO,JDK 1.4引入
  • AIO (Asynchronous IO):异步非阻塞IO,JDK 1.7引入

1.2 同步与异步、阻塞与非阻塞

// 同步阻塞:调用者等待结果返回
public String syncBlocking() {
    return "数据读取完成";  // 线程会一直等待
}

// 同步非阻塞:调用者主动轮询结果
public String syncNonBlocking() {
    while (true) {
        String result = tryRead();
        if (result != null) return result;
        // 继续轮询
    }
}

// 异步非阻塞:通过回调获取结果
public void asyncNonBlocking(Callback callback) {
    CompletableFuture.supplyAsync(() -> "数据读取完成")
                     .thenAccept(callback::onComplete);
}

2. BIO (Blocking IO) 详解

2.1 BIO基本特点

  • 同步阻塞模式
  • 一个连接对应一个线程
  • 线程在IO操作时会被阻塞
  • 适合连接数较少的场景

2.2 BIO实现示例

public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("BIO服务器启动,监听端口: 8080");
        
        while (true) {
            Socket clientSocket = serverSocket.accept();  // 阻塞等待
            new Thread(() -> handleClient(clientSocket)).start();
        }
    }
    
    private static void handleClient(Socket clientSocket) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
             PrintWriter writer = new PrintWriter(
                clientSocket.getOutputStream(), true)) {
            
            String inputLine;
            while ((inputLine = reader.readLine()) != null) {
                System.out.println("收到消息: " + inputLine);
                writer.println("Echo: " + inputLine);
                if ("bye".equalsIgnoreCase(inputLine)) break;
            }
        } catch (IOException e) {
            System.err.println("处理客户端连接异常: " + e.getMessage());
        }
    }
}

3. NIO (Non-blocking IO) 详解

3.1 NIO核心组件

  • Channel(通道):数据传输的管道
  • Buffer(缓冲区):数据容器
  • Selector(选择器):多路复用器

3.2 NIO实现示例

public class NIOServer {
    public void start() throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress(8080));
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        
        System.out.println("NIO服务器启动,监听端口8080");
        
        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) continue;
            
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                
                if (key.isAcceptable()) {
                    handleAccept(key, selector);
                } else if (key.isReadable()) {
                    handleRead(key);
                }
                keyIterator.remove();
            }
        }
    }
    
    private void handleAccept(SelectionKey key, Selector selector) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept();
        
        if (clientChannel != null) {
            clientChannel.configureBlocking(false);
            clientChannel.register(selector, SelectionKey.OP_READ, 
                                 ByteBuffer.allocate(1024));
        }
    }
    
    private void handleRead(SelectionKey key) throws IOExcept

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务