I/O几种类型

5 阅读3分钟

1. 同步 I/O

  • 定义:I/O 操作按顺序执行,程序会等待当前 I/O 操作完成后再继续执行。

  • 特点

    • 简单易理解,适合简单的应用场景。
    • 可能导致程序等待,从而降低效率。

2. 异步 I/O

  • 定义:I/O 操作不会阻塞程序,程序可以在等待 I/O 操作完成的同时执行其他任务。

  • 特点

    • 提高了程序的并发性能。
    • 复杂性较高,需要处理回调或事件通知。

3. 阻塞 I/O

  • 定义:调用会阻塞程序,直到 I/O 操作完成。

  • 特点

    • 操作简单,常用于传统应用。
    • 可能导致资源浪费,因为程序在等待时无法执行其他任务。

4. 非阻塞 I/O

  • 定义:调用不会阻塞程序,如果不能立即完成,操作会返回错误或特殊值。

  • 特点

    • 程序可以继续执行其他任务,提高了资源利用率。
    • 需要轮询或使用回调来检查 I/O 状态。

5. 文件 I/O

  • 定义:涉及文件的读写操作。

  • 特点

    • 常用于数据存储和读取。
    • 可能受限于磁盘速度和文件系统性能。

6. 网络 I/O

  • 定义:涉及网络通信的 I/O 操作,如发送和接收数据包。

  • 特点

    • 常用于客户端-服务器通信。
    • 受网络带宽和延迟影响。

7. 内存映射 I/O

  • 定义:使用内存映射文件进行 I/O 操作,将文件的一部分映射到内存地址空间。

  • 特点

    • 提高了文件读写的效率。
    • 适合处理大文件或需要频繁访问的数据。

8. 字符 I/O 和块 I/O

  • 字符 I/O

    • 逐字符地进行输入输出。
    • 适合处理文本数据。
    • 速度较慢,因为每次操作处理一个字符。
  • 块 I/O

    • 以数据块为单位进行输入输出。
    • 适合处理大量数据。
    • 提高了吞吐量,适合磁盘和网络传输。

选择合适的 I/O 模型

  • 应用场景:根据应用需求选择合适的 I/O 模型。例如,Web 服务器通常使用异步或非阻塞 I/O 以提高并发性能。
  • 性能考虑:需要权衡 I/O 模型的复杂性和性能收益。
  • 资源限制:考虑系统资源,如内存和 CPU,以选择合适的 I/O 模型。

阻塞I/O

在 Java 中,阻塞 I/O 是指在 I/O 操作完成之前,线程会被阻塞,无法执行其他任务。以下是 Java 中常见的阻塞 I/O 类型:

1. 文件 I/O

  • FileInputStream / FileOutputStream:用于读取和写入文件的字节流。
  • FileReader / FileWriter:用于读取和写入文件的字符流。

2. 网络 I/O

  • Socket:用于 TCP 网络通信。accept()read()write() 方法在等待连接或数据时会阻塞。
  • ServerSocket:用于监听传入的 TCP 连接,accept() 方法会阻塞直到有连接到达。

3. 标准输入输出

  • System.in:读取控制台输入时会阻塞,直到用户输入数据。
  • System.out:通常用于输出数据到控制台,虽然它本身不阻塞,但等待用户处理输出可能会导致程序等待。

4. NIO(New I/O)中的阻塞模式

  • FileChannelSocketChannel:在默认情况下是阻塞的,尽管 NIO 提供了非阻塞的能力,但如果不特别设置为非阻塞模式,它们仍然是阻塞的。

示例

以下是一个简单的阻塞网络 I/O 示例:

import java.io.*;
import java.net.*;

public class BlockingIOSocketExample {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            System.out.println("Server is listening on port 8080");
            // 阻塞等待连接
            Socket socket = serverSocket.accept();
            System.out.println("Client connected");

            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter output = new PrintWriter(socket.getOutputStream(), true);

            String message;
            // 阻塞读取客户端消息
            while ((message = input.readLine()) != null) {
                System.out.println("Received: " + message);
                output.println("Echo: " + message);
            }

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

总结

阻塞 I/O 简单易用,但在需要处理大量并发请求时可能导致性能瓶颈。这时可以考虑使用 Java NIO 的非阻塞模式或使用异步 I/O(如 AsynchronousSocketChannel)来提高性能。