Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用

简介: Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用

Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用

Java 中的 I/O 操作主要包括三种模式:BIO(阻塞 I/O)、NIO(非阻塞 I/O)和 AIO(异步 I/O)。每种模式都有其独特的应用场景和特性。以下是对这三种 I/O 模式的详细介绍:


一、BIO(Blocking I/O)

1. 特性
  • 阻塞模式:在进行读写操作时,如果没有数据可读或可写,线程会阻塞,直到操作完成。
  • 简单易用:编程模型简单,易于理解和使用。
2. 适用场景
  • 适用于连接数较少且固定的场景,例如少量的数据库连接操作。
3. 示例代码
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        while (true) {
            Socket socket = serverSocket.accept(); // 阻塞等待客户端连接
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                     PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {
                    String message;
                    while ((message = reader.readLine()) != null) {
                        System.out.println("Received: " + message);
                        writer.println("Echo: " + message);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}


二、NIO(Non-blocking I/O)

1. 特性
  • 非阻塞模式:通道(Channel)和缓冲区(Buffer)相结合,通过选择器(Selector)可以实现非阻塞的多路复用。
  • 高效:在单个线程中管理多个通道,通过少量线程处理大量连接,提高了资源利用率。
2. 适用场景
  • 适用于连接数较多且连接时间较长的场景,例如大型聊天服务器、HTTP 服务器。
3. 关键组件

通道(Channel):如 FileChannel, SocketChannel, ServerSocketChannel 等。

缓冲区(Buffer):如 ByteBuffer, CharBuffer 等。

选择器(Selector):管理多个通道的 I/O 操作。

4. 示例代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class NIOServer {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8080));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                if (key.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = socketChannel.read(buffer);
                    if (bytesRead > 0) {
                        buffer.flip();
                        System.out.println("Received: " + new String(buffer.array(), 0, bytesRead));
                        socketChannel.write(ByteBuffer.wrap(("Echo: " + new String(buffer.array(), 0, bytesRead)).getBytes()));
                    } else if (bytesRead == -1) {
                        socketChannel.close();
                    }
                }
            }
        }
    }
}


三、AIO(Asynchronous I/O)

1. 特性
  • 异步模式:操作是异步和非阻塞的,通过回调函数(CompletionHandler)处理操作结果。
  • 高性能:适用于高延迟、大吞吐量的应用场景。
2. 适用场景
  • 适用于连接数极多且连接时间长的场景,例如高并发的聊天服务器、视频直播服务器。
3. 关键组件
  • 异步通道(AsynchronousChannel):如 AsynchronousSocketChannel,
  • AsynchronousServerSocketChannel 等。
  • CompletionHandler:处理异步操作的回调。
4. 示例代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

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

        serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
            @Override
            public void completed(AsynchronousSocketChannel result, Void attachment) {
                serverChannel.accept(null, this); // 接受下一个连接
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                    @Override
                    public void completed(Integer bytesRead, ByteBuffer buffer) {
                        if (bytesRead > 0) {
                            buffer.flip();
                            System.out.println("Received: " + new String(buffer.array(), 0, bytesRead));
                            result.write(ByteBuffer.wrap(("Echo: " + new String(buffer.array(), 0, bytesRead)).getBytes()));
                            buffer.clear();
                            result.read(buffer, buffer, this); // 继续读取
                        } else {
                            try {
                                result.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    @Override
                    public void failed(Throwable exc, ByteBuffer attachment) {
                        exc.printStackTrace();
                    }
                });
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                exc.printStackTrace();
            }
        });

        // 为了保持服务器运行
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

总结

  • BIO(Blocking I/O):适合简单、少量连接的应用场景,编程简单但性能较低。
  • NIO(Non-blocking I/O):适合高并发、大量连接的应用,使用复杂但性能较好。
  • AIO(Asynchronous I/O):适合超高并发、长连接的应用,异步非阻塞,性能最佳。


根据不同应用场景和性能需求,选择适合的 I/O 模型,以实现高效的网络编程。

目录
相关文章
|
30天前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
65 0
|
2月前
|
数据采集 监控 Oracle
GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩
阿里巴巴是 GraalVM 全球顾问委员会的唯一中国代表,阿里云程序语言与编译器团队和可观测团队合作实现了 GraalVM 应用的无侵入可观测能力,并在 ARMS 平台上线了该功能。目前在 GraalVM 24 中发布的是支持 Java agent 的第一步,其余能力将在 GraalVM 的后续版本中陆续发布。
223 21
|
3月前
|
缓存 运维 Java
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
117 4
|
4月前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
147 0
|
6月前
|
监控 Java API
探索Java NIO:究竟在哪些领域能大显身手?揭秘原理、应用场景与官方示例代码
Java NIO(New IO)自Java SE 1.4引入,提供比传统IO更高效、灵活的操作,支持非阻塞IO和选择器特性,适用于高并发、高吞吐量场景。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector),能实现多路复用和异步操作。其应用场景涵盖网络通信、文件操作、进程间通信及数据库操作等。NIO的优势在于提高并发性和性能,简化编程;但学习成本较高,且与传统IO存在不兼容性。尽管如此,NIO在构建高性能框架如Netty、Mina和Jetty中仍广泛应用。
145 3
|
6月前
|
存储 监控 Java
Java的NIO体系
通过本文的介绍,希望您能够深入理解Java NIO体系的核心组件、工作原理及其在高性能应用中的实际应用,并能够在实际开发中灵活运用这些知识,构建高效的Java应用程序。
174 5
|
6月前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
113 1
|
6月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
190 6
|
7月前
|
Java
BIO、NIO、AIO 有什么区别
BIO(阻塞I/O)模型中,服务器实现模式为一个连接一个线程;NIO(非阻塞I/O)使用单线程或少量线程处理多个请求;AIO(异步I/O)则是在NIO基础上进一步优化,采用事件通知机制,提高并发处理能力。
234 6