Java IO 与 BIO、NIO、AIO 详解

在 Java 中,I/O(输入/输出)操作是与外部系统(如文件、网络等)进行数据交换的基础。Java 提供了多种 I/O 机制,包括传统的阻塞式 I/O(BIO)、非阻塞式 I/O(NIO)和异步 I/O(AIO)。本文将详细探讨这三种 I/O 模型的特点、区别及其适用场景。

1 BIO(Blocking I/O)

BIO 是一种同步阻塞 I/O 模型。在这种模型中,线程在执行 I/O 操作时会被阻塞,直到操作完成。BIO 适用于连接数较少且稳定的场景。

特点

  • 同步阻塞:线程在执行 I/O 操作时被阻塞,无法处理其他任务。
  • 简单易用:API 直观简单,易于理解和使用。
  • 性能较低:每个连接都需要一个单独的线程,适用于连接数较少的场景。

示例代码

java 复制代码
public class BioFileDemo {
    public static void main(String[] args) {
        BioFileDemo demo = new BioFileDemo();
        demo.writeFile();
        demo.readFile();
    }

    // 使用 BIO 写入文件
    public void writeFile() {
        String filename = "logs/itwanger/paicoding.txt";
        try {
            FileWriter fileWriter = new FileWriter(filename);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

            bufferedWriter.write("学编程就上技术派");
            bufferedWriter.newLine();

            System.out.println("写入完成");
            bufferedWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 使用 BIO 读取文件
    public void readFile() {
        String filename = "logs/itwanger/paicoding.txt";
        try {
            FileReader fileReader = new FileReader(filename);
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println("读取的内容: " + line);
            }

            bufferedReader.close();
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2 NIO(New I/O 或 Non-blocking I/O)

NIO 是一种同步非阻塞 I/O 模型。在这种模型中,线程在等待 I/O 时可以执行其他任务,通过 Selector 监控多个 Channel 上的事件,提高性能和可伸缩性。NIO 适用于高并发场景。

特点

  • 同步非阻塞:线程在等待 I/O 时可执行其他任务。
  • I/O 多路复用 :通过 Selector 监控多个 Channel 上的事件。
  • 性能较高:单个线程可以处理多个连接,适用于高并发场景。

示例代码

java 复制代码
public class NioFileDemo {
    public static void main(String[] args) {
        NioFileDemo demo = new NioFileDemo();
        demo.writeFile();
        demo.readFile();
    }

    // 使用 NIO 写入文件
    public void writeFile() {
        Path path = Paths.get("logs/itwanger/paicoding.txt");
        try {
            FileChannel fileChannel = FileChannel.open(path, EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE));

            ByteBuffer buffer = StandardCharsets.UTF_8.encode("学编程就上技术派");
            fileChannel.write(buffer);

            System.out.println("写入完成");
            fileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 使用 NIO 读取文件
    public void readFile() {
        Path path = Paths.get("logs/itwanger/paicoding.txt");
        try {
            FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ);
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            int bytesRead = fileChannel.read(buffer);
            while (bytesRead != -1) {
                buffer.flip();
                System.out.println("读取的内容: " + StandardCharsets.UTF_8.decode(buffer));
                buffer.clear();
                bytesRead = fileChannel.read(buffer);
            }

            fileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3 AIO(Asynchronous I/O)

AIO 是一种异步非阻塞 I/O 模型。在这种模型中,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程。AIO 进一步提高了并发处理能力,适用于高吞吐量场景。

特点

  • 异步非阻塞:线程发起 I/O 请求后立即返回,通过回调函数处理结果。
  • 高性能:适用于高吞吐量场景,充分利用操作系统参与并发操作。
  • 复杂性较高:编程复杂度较高,需要处理回调函数。

示例代码

java 复制代码
public class AioDemo {
    public static void main(String[] args) {
        AioDemo demo = new AioDemo();
        demo.writeFile();
        demo.readFile();
    }

    // 使用 AsynchronousFileChannel 写入文件
    public void writeFile() {
        Path path = Paths.get("logs/itwanger/paicoding.txt");
        try {
            AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            ByteBuffer buffer = StandardCharsets.UTF_8.encode("学编程就上技术派");
            Future<Integer> result = fileChannel.write(buffer, 0);
            result.get();

            System.out.println("写入完成");
            fileChannel.close();
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    // 使用 AsynchronousFileChannel 读取文件
    public void readFile() {
        Path path = Paths.get("logs/itwanger/paicoding.txt");
        try {
            AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            fileChannel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    attachment.flip();
                    System.out.println("读取的内容: " + StandardCharsets.UTF_8.decode(attachment));
                    attachment.clear();
                    try {
                        fileChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    System.out.println("读取失败");
                    exc.printStackTrace();
                }
            });

            Thread.sleep(1000);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4 三种 I/O 模型的区别

模型 同步/异步 阻塞/非阻塞 适用场景
BIO 同步 阻塞 连接数较少且稳定的场景
NIO 同步 非阻塞 高并发场景 (即连接数目多且连接比较短的场景)
AIO 异步 非阻塞 高吞吐量场景 (即连接数目多且连接比较长的场景)

5 总结

  • BIO:采用阻塞式 I/O 模型,线程在执行 I/O 操作时被阻塞,无法处理其他任务,适用于连接数较少且稳定的场景。
  • NIO :使用非阻塞 I/O 模型,线程在等待 I/O 时可执行其他任务,通过 Selector 监控多个 Channel 上的事件,提高性能和可伸缩性,适用于高并发场景。
  • AIO:采用异步 I/O 模型,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程,进一步提高了并发处理能力,适用于高吞吐量场景。

理解这三种 I/O 模型的特点和适用场景,有助于在实际开发中选择合适的 I/O 机制,以提高程序的性能和可扩展性。

6 思维导图

7 参考链接

一文彻底解释清楚Java 中的NIO、BIO和AIO

相关推荐
APIshop2 分钟前
Python 零基础写爬虫:一步步抓取商品详情(超细详解)
开发语言·爬虫·python
q***614111 分钟前
Spring中Aware的用法以及实现
java·数据库·spring
代码or搬砖32 分钟前
SpringMVC的执行流程
java·spring boot·后端
AI科技星38 分钟前
为什么宇宙无限大?
开发语言·数据结构·经验分享·线性代数·算法
星空的资源小屋43 分钟前
跨平台下载神器ArrowDL,一网打尽所有资源
javascript·笔记·django
Appreciate(欣赏)1 小时前
JAVA使用poi类读取xlxs文件内容拼接成添加数据SQL
java·开发语言·sql
Xudde.1 小时前
Quick2靶机渗透
笔记·学习·安全·web安全·php
极光代码工作室1 小时前
基于SpringBoot的流浪狗管理系统的设计与实现
java·spring boot·后端
oioihoii1 小时前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
开发语言·c++
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于JAVA的恒星酒店客房管理系统为例,包含答辩的问题和答案
java·开发语言