Home  >  Article  >  Java  >  Comparative analysis of Java input and output IO, NIO and AIO

Comparative analysis of Java input and output IO, NIO and AIO

王林
王林forward
2023-05-08 23:07:071581browse

    1. History of Java I/O development

    Comparative analysis of Java input and output IO, NIO and AIO

    Java IO (Input/Output) is used in the Java language An API for reading and writing data, it provides a series of classes and interfaces for reading and writing various types of data. The following is a brief introduction to the development history of Java IO:

    • JDK 1.0 (1996) The original Java IO only supported byte streams (InputStream, OutputStream) and character streams (Reader, Writer) Two types, based on the blocking IO (BIO) model.

    • JDK 1.1 (1997) JDK 1.1 introduced the NIO (New IO) package, supported concepts such as buffer and channel, and provided more efficient IO The operation mode can realize non-blocking IO (NIO) mode.

    • JDK 1.4 (2002) JDK 1.4 adds the NIO.2 API, also known as Java NIO with buffers, which provides more powerful file processing functions and more efficient IO operations.

    • JDK 7 (2011) JDK 7 introduces an improved version of NIO.2 - NIO.2 with Completion Ports, also known as AIO (Asynchronous IO), supports asynchronous The IO method has advantages when handling a large number of concurrent requests.

    The following are the differences between the three:

    Comparative analysis of Java input and output IO, NIO and AIO

    • Blocking IO (BIO) BIO is Java's original IO model, which uses blocking methods to perform data reading and writing operations. That is, when a thread is performing an IO operation, if there is no data to read, the thread will block and wait until there is data to read or it times out. BIO is suitable for handling scenarios where the number of connections is relatively small and fixed, but the concurrency capability is insufficient.

    • Non-blocking IO (NIO) NIO is a new IO model introduced in Java 1.4. It uses a multiplexer (Selector) mechanism to manage multiple channels at the same time through a small number of threads. , achieving the effect of a single thread processing multiple requests at the same time. NIO has high concurrency, high throughput and higher reliability, and is suitable for handling scenarios with a large number of connections and short connection times.

    • Asynchronous IO (AIO) AIO is an IO model supported by Java 1.7. It uses an event-driven approach to read and write data. When the data is ready, it is performed in the callback function. deal with. Unlike NIO, AIO's read and write operations are asynchronous, and there is no need to poll to check whether the data is ready. AIO is suitable for handling scenarios with a large number of connections, long connection times, and many read and write operations.

    2. Java IO

    2.1 Introduction

    In Java programming, IO (Input/Output) operations are very common operations, which involve to file reading and writing, network communication, etc. Java provides various classes to support these operations. This article will start with the basic knowledge of IO, and gradually deepen, introducing all aspects of Java IO.

    2.2 Basic concepts

    2.2.1 Input stream and output stream

    In Java, input stream (InputStream) and output stream (OutputStream) are two important abstractions kind. The input stream represents the source of input data, which can be files, network connections, pipes, etc.; the output stream represents the destination of output data, which can be files, network connections, pipes, etc. Input streams and output streams are used in a similar way, by creating a stream object and then using the corresponding method interface to perform read and write operations.

    2.2.2 Byte stream and character stream

    The IO operations in Java can also be divided into two types: byte stream and character stream. The byte stream operates in units of bytes (byte) and is suitable for processing binary data, such as images, audio, etc.; while the character stream operates in units of characters (char) and is suitable for processing text data, such as text files, etc. In Java, byte streams are mainly implemented by the InputStream and OutputStream classes and their subclasses, while character streams are mainly implemented by the Reader and Writer classes and their subclasses.

    2.2.3 Buffered stream

    When performing IO operations, we may need to perform frequent reading and writing operations, and frequent reading and writing may cause performance problems. In order to solve this problem, Java provides a buffered stream (Buffered Stream) to improve the efficiency of IO operations. Buffered streams can reduce the number of accesses to underlying resources through the internal cache area, thereby improving the efficiency of data reading and writing.

    2.3 Use of Java IO

    2.3.1 File reading and writing

    File reading and writing in Java is one of the most common operations in development. The following is an example of reading the contents of a file and outputting it:

        try (FileInputStream fis = new FileInputStream("test.txt");
             InputStreamReader isr = new InputStreamReader(fis);
             BufferedReader br = new BufferedReader(isr)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    In this example, we use classes such as FileInputStream, InputStreamReader and BufferedReader to complete file reading. First, we create an input stream object through the FileInputStream class and specify the name of the file to be read; then we use InputStreamReader to convert the byte stream into a character stream, and then use BufferedReader to read the text content line by line.

    Similarly, writing files in Java is also very simple. Here is an example of writing a file:

    try (FileOutputStream fos = new FileOutputStream("test.txt");
         OutputStreamWriter osw = new OutputStreamWriter(fos);
         BufferedWriter bw = new BufferedWriter(osw)) {
        bw.write("Hello, world!");
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileOutputStream、OutputStreamWriter和BufferedWriter等类来完成文件的写入。首先,我们通过FileOutputStream类创建了一个输出流对象,并指定了要写入的文件名称;然后通过OutputStreamWriter将字节流转换为字符流,再通过BufferedWriter实现按行写入文本内容。

    3、Java NIO

    3.1 简介

    Java NIO(New IO)是Java SE 1.4引入的一个新的IO API,它提供了比传统IO更高效、更灵活的IO操作。与传统IO相比,Java NIO的优势在于它支持非阻塞IO和选择器(Selector)等特性,能够更好地支持高并发、高吞吐量的应用场景。本文将从NIO的基础知识讲起,逐步深入,介绍Java NIO的各个方面。

    3.2 核心概念

    3.2.1 选择器(Selector)

    选择器是Java NIO中的一个重要组件,它可以用于同时监控多个通道的读写事件,并在有事件发生时立即做出响应。选择器可以实现单线程监听多个通道的效果,从而提高系统吞吐量和运行效率。

    3.2.2 通道(Channel)

    通道是一个用于读写数据的对象,类似于Java IO中的流(Stream)。与流不同的是,通道可以进行非阻塞式的读写操作,并且可以同时进行读写操作。通道分为两种类型:FileChannel和SocketChannel,分别用于文件和网络

    通信。

    3.2.3 缓冲区(Buffer)

    在Java NIO中,所有数据都是通过缓冲区对象进行传输的。缓冲区是一段连续的内存块,可以保存需要读写的数据。缓冲区对象包含了一些状态变量,例如容量(capacity)、限制(limit)、位置(position)等,用于控制数据的读写。

    3.3 Java NIO的使用

    3.3.1 缓冲区操作

    Java NIO中的缓冲区操作主要包括数据读取和数据写入两种操作。下面是一个简单的缓冲区读取示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    try (FileChannel channel = new FileInputStream("test.txt").getChannel()) {
        int bytesRead = channel.read(buffer);
        while (bytesRead != -1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }
            buffer.clear();
            bytesRead = channel.read(buffer);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的读取。首先,我们通过FileInputStream类创建了一个输入流对象,然后通过getChannel()方法获取到对应的通道对象;接着,我们创建了一个容量为1024字节的ByteBuffer对象,并调用read()方法从通道中读取数据,将读取到的数据保存在缓冲区中。读取完成后,我们通过flip()方法将缓冲区切换为读模式,并使用hasRemaining()和get()方法逐个读取数据;最后通过clear()方法清空缓冲区,准备进行下一轮读取。

    Java NIO中的缓冲区写操作也非常类似,下面是一个简单的缓冲区写入示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    try (FileChannel channel = new FileOutputStream("test.txt").getChannel()) {
        channel.write(buffer);
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的写入。首先,我们通过ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象;然后,我们通过FileOutputStream类创建了一个输出流对象,再通过getChannel()方法获取到对应的通道对象;接着,我们调用write()方法将缓冲区中的数据写入通道中,完成文件写入操作。

    3.3.2 通道操作

    Java NIO中的通道(Channel)是用于进行数据传输的对象。通道可以连接到源或目标节点,用于读取和写入数据。与传统的Java IO不同,NIO中的通道可以实现非阻塞式地读写数据,从而提高了应用程序的性能和并发处理能力。

    要使用通道进行读写操作,首先需要打开通道。Java NIO中有多种类型的通道,每种通道都提供了自己的打开方式。例如,要打开一个文件通道,可以通过FileInputStream或FileOutputStream对象获取对应的FileChannel对象,如下所示:

        FileChannel channel = new FileInputStream("file.txt").getChannel();

    读取数据 一旦打开了通道,就可以开始读取数据。在NIO中,数据通过缓冲区进行传输。要读取数据,需要将数据存储在缓冲区中,然后从缓冲区中读取数据。以下是一个简单的读取操作示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // 从通道中读取数据
    int bytesRead = channel.read(buffer);
    while (bytesRead != -1) {
        // 切换为读模式
        buffer.flip();
        // 读取缓冲区中的数据
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }
        // 清空缓冲区
        buffer.clear();
        bytesRead = channel.read(buffer);
    }

    在这个示例中,我们首先创建了一个容量为1024字节的ByteBuffer对象,并使用channel.read()方法从文件通道中读取数据。读取到数据后,我们将ByteBuffer切换为读模式,再使用hasRemaining()和get()方法逐个读取缓冲区中的数据。

    写入数据 要写入数据,也需要将数据存储在缓冲区中,然后将缓冲区中的数据写入到通道中。以下是一个简单的写入操作示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    // 将数据写入通道
    channel.write(buffer);

    在这个示例中,我们首先使用ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象,在通过channel.write()方法将ByteBuffer中的数据写入到通道中。

    4、Java AIO

    Java AIO(Asynchronous IO)是一种基于事件和回调的IO模型,相比Java BIO(Blocking IO)和Java NIO(Non-blocking IO),它具有更高的并发性、更高的吞吐量和更高的可靠性。本文将介绍Java AIO的原理、特点和应用。

    4.1 Principle of Java AIO

    Java AIO uses asynchronous IO for data reading and writing operations. Unlike Java NIO, it does not need to poll to check whether the data is ready, but the operating system Finish. When the data is ready, the operating system will notify the application and process it in the callback function.

    AIO uses three core components: AsynchronousChannel, CompletionHandler and
    AsynchronousServerSocketChannel. Among them, AsynchronousChannel is the channel for reading/writing data, CompletionHandler is the callback method when the I/O operation is completed, and AsynchronousServerSocketChannel is the asynchronous server-side socket channel used to monitor the client's connection request.

    When the data is ready, the operating system will notify the application and execute the callback method in the callback function when the I/O operation is completed. This avoids the situation where threads are blocked waiting for I/O operations to be completed, thereby improving the efficiency and concurrent processing capabilities of the program.

    4.2 Characteristics of Java AIO

    • High concurrency: Java AIO uses asynchronous IO for data reading and writing operations, which can achieve high concurrency processing capabilities.

    • High throughput: Java AIO supports asynchronous read and write operations and can handle multiple requests at the same time, thus improving the efficiency and throughput of data reading and writing.

    • High reliability: Because Java AIO uses asynchronous IO for data reading and writing operations, it can avoid thread blocking waiting for I/O operations to be completed, thus improving the reliability of the program.

    • Simple and easy to use: Java AIO provides a simple and easy-to-use API, and you can implement asynchronous IO operations without writing complex code.

    4.3 Applications of Java AIO

    Java AIO is suitable for scenarios that require a large number of concurrent connections, but each connection has little data interaction, such as message-based applications Programs, remote procedure calls (RPC), etc. In these application scenarios, AIO can greatly improve the performance and concurrent processing capabilities of the program, thereby meeting users' requirements for high throughput and low latency.

    In addition, Java AIO can also be used to develop high-performance network servers, such as chat room servers, online game servers, etc. Because AIO supports asynchronous reading of input and output streams, it can handle multiple client requests at the same time, effectively improving the server's concurrent processing capabilities.

    Summary

    As a high-performance, high-concurrency IO model, Java AIO has many advantages, but there are also some shortcomings. For example, for small load connections, AIO overhead may Resulting in performance degradation. Therefore, in practical applications, various factors need to be weighed and evaluated and selected based on actual needs.

    5. Related interview questions

    1. What are Java IO and NIO?

    Java IO (Input/Output) is a traditional input and output operation in Java, using byte streams and character streams for data transmission.
    Java NIO (New Input/Output) is a new input and output API introduced in Java 1.4, which processes data more efficiently.

    2. What are blocking and non-blocking IO?

    Blocking IO (Blocking IO) will wait until the IO is completed during an IO operation, during which no other operations can be performed.
    Non-blocking IO (Non-blocking IO) does not wait forever when performing IO operations, but returns the result immediately. If the IO has not been completely completed, you can continue to do other things.

    3. What is a buffer? What types of buffers are there?

    The buffer is an array used to store data. When performing IO operations, the buffer needs to be used to read and write data.
    Java's buffers are divided into byte buffers (ByteBuffer, CharBuffer, ShortBuffer, etc.) and direct buffers (DirectByteBuffer, DirectCharBuffer, DirectShortBuffer, etc.).

    4. What is Channel?

    A channel is an object used for data transmission in NIO. It can be connected to the source or destination node for reading and writing data.

    5. What is a selector?

    The selector is an object in NIO. It can poll the channels registered on it to check whether they have events (such as readable, writable, etc.), thus avoiding blocking IO. Need to wait for IO to complete.

    6. What is the difference between Java IO and NIO?

    Java IO transmits data based on streams, while NIO transmits data based on buffers and channels.
    Java IO is blocking, while NIO can be in blocking or non-blocking mode.
    Java IO uses more threads, and each IO operation requires the creation of a thread, while NIO can use a single thread to handle multiple IO operations.

    7. What is FileChannel?

    File channel is the channel used in NIO to read and write files. It supports advanced features such as random access and memory mapped files.

    8. Which one is faster, Java IO or NIO?

    In the case of large amounts of small data, Java IO may be faster because it can read all the data at once through the buffer.
    In the case of a large number of large blocks of data, NIO may be faster because it can use zero-copy technology to read data directly from disk into memory, reducing the overhead of data copying.

    The above is the detailed content of Comparative analysis of Java input and output IO, NIO and AIO. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete