preface

I/O, usually the input and output of data between internal storage (memory) and external storage (disk).

Java provides some apis for developers to read and write external data or files. These apis are called Java IO. With the development of Java, there are three IO types: BIO, NIO, and AIO.

Before we talk about BIO, NIO, and AIO, let’s clarify four concepts: synchronous asynchrony and blocking non-blocking.

Synchronous/asynchronous

Synchronous/asynchronous focuses on message communication mechanisms.

  • Synchronization (Synchronous)After a call is made, the caller must wait for the result of the call to return before continuing.
  • Asynchronous (Asynchronous)After a call is initiated, the caller can continue to perform subsequent operations. After the call is completed, the caller returns the result to the caller.

For example, synchronization is when the main thread starts executing and calls one of the sum() methods. The main thread waits for the sum() method to complete and return the result before executing further program code. Asynchronous means that the main thread calls sum(), and another thread executes the internal logic of sum(). The main thread can execute the code after sum() is called, without waiting for the sum() result to return.

Blocked/non-blocked

Blocking/non-blocking concerns the state of the program while it waits for the result of the call. The difference is whether the program is blocked after the first IO request is made.

  • blockingThe current thread is suspended until the result of the call is returned. The calling thread will return only after the result is returned.
  • non-blockingIt means that the current thread does not block until the result of the call is returned.

Synchronous/asynchronous is often confused with blocking/non-blocking.

Synchronous/asynchronous refers to the communication mechanism of the message. Synchronous means that the current thread needs to get the execution result and then return it. Asynchronous means that the current thread does not need to wait for the execution result, but can execute the subsequent operations of the current thread. Blocked/non-blocked refers to the state of the thread after the program is called. Based on the same thread, Blocked refers to the state that the thread is Blocked after the call, while non-blocked refers to the state that the thread is still Running after the call. The difference between Blocked and non-blocked is whether the current thread is in the Blocked state. So, they don’t refer to one dimension.

BIO, NIO, AIO

Let’s use the classic example of boiling water to illustrate the difference between these three concepts.

BIO(Block IO) is a traditional synchronous blocking communication mode. It is simple and easy to use, but has low concurrent processing capability, time-consuming communication, and depends on network speed.

NIO(Non-BoCK) IO is a synchronous non-blocking communication mode. It is a new function optimized for network transmission efficiency.

AIO(Asynchronous IO) is an Asynchronous non-blocking communication mode.

Synchronous blocking works by going to the kitchen, boiling water, and waiting by the kettle until it boils.

Synchronous non-blocking mode means going to the kitchen, starting to boil water, this time not waiting by the kettle, returning to the living room to watch TV, and checking every few minutes to see if the water is boiling.

Asynchronous non-blocking mode is when you go to the kitchen, start boiling water, go back to the living room and watch TV until you hear the kettle beep.

Synchronous vs asynchronous: How does the called party return the result of the call? (How do we know when the kettle is boiling, whether it is active or passive?)

Blocking vs non-blocking: is the state of the caller blocked after the call? (After we turn the kettle on, do we wait by the kettle for the water to boil)

Applicable scenario

BIO is suitable for a small and fixed number of connections. It requires a lot of server resources, and concurrency is limited to the application. It was the only choice before JDK1.4, but the application is intuitive and easy to understand.

NIO is suitable for architectures with high number of connections and short connections, such as chat servers, where concurrency is limited to applications and programming is complex, and is supported in JDK1.4.

AIO mode is suitable for the architecture with a large number of connections and long connections, such as album server, which fully calls OS to participate in concurrent operations. Programming is complicated, and JDK7 starts to support it.

In actual combat

Let’s look at the differences between the three architectural patterns from a code perspective.

BIO

Prior to JDK1.4, writing network requests in Java used to set up a ServerSocket. When the client set up the socket, it would ask if there was a thread available to handle it. If there was none, it would either wait or be rejected.

Write files

public class WriteFileTest {
    public static void main(String[] args) throws IOException {
        User user = new User();
        user.setAge(10);
        user.setName("feiyangyang");

        ObjectOutputStream oos = null;

        try {
            oos = new ObjectOutputStream(new FileOutputStream("bioFile"));
            oos.writeObject(user);
        } catch (IOException e) {
            e.printStackTrace();
        } finally{ oos.close(); }}}Copy the code

Read the file

public class ReadFileTest {
    public static void main(String[] args) throws IOException {
        File bioFile = new File("bioFile");
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(bioFile));
            User user = (User) ois.readObject();
            System.out.println(user);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally{ ois.close(); }}}Copy the code

NIO

In Java, an API dedicated to non-blocking I/O has been provided since JDK1.4, and you can find related classes and interfaces in the java.nio package and its subpackages.

The API consists of three main parts:

  • Buffer (Buffers)
  • Channel (Channels)
  • Core class composition of non-blocking I/O

Write files

public class WriteFileTest {
    public static void main(String[] args) {
        String fileName = "nioFile";
        try (FileOutputStream fos = new FileOutputStream(new File(fileName))) {
            FileChannel channel = fos.getChannel();
            ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode("Hello hello...");
            int length = 0;
            while((length = channel.write(byteBuffer)) ! =0) {
                System.out.println("Write length:"+ length); }}catch(IOException e) { e.printStackTrace(); }}}Copy the code

Read the file

public class ReadFileTest {
    public static void main(String[] args) throws IOException {
        String fileName = "C:\IODemo\nioFile";
        try (FileInputStream fis = new FileInputStream(new File(fileName)); FileChannel channel = fis.getChannel()) {
            int capacity = 100;
            ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
            int length = -1;
            while((length = channel.read(byteBuffer)) ! = -1) {
                byteBuffer.clear();
                byte[] array = byteBuffer.array();
                System.out.write(array, 0, length); System.out.println(); }}catch(FileNotFoundException e) { e.printStackTrace(); }}}Copy the code

AIO

Use the java.nio package classes Java.nio AsynchronousFileChannel and CompletionHandler for channels and handlers, respectively.

Write files

public class WriteFileTest {
    public static void main(String[] args) throws IOException {
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
                Paths.get("aioFile.txt"), StandardOpenOption.READ,
                StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {

            @Override
            public void completed(Integer result, Object attachment) {
                System.out.println("Attachment: " + attachment + "" + result
                        + " bytes written");
                System.out.println("CompletionHandler Thread ID: "
                        + Thread.currentThread().getId());
            }

            @Override
            public void failed(Throwable e, Object attachment) {
                System.err.println("Attachment: " + attachment + " failed with:"); e.printStackTrace(); }}; System.out.println("Main Thread ID: " + Thread.currentThread().getId());
        fileChannel.write(ByteBuffer.wrap("Sample".getBytes()), 0."First Write",
                handler);
        fileChannel.write(ByteBuffer.wrap("Box".getBytes()), 0."Second Write", handler); }}Copy the code

Read the file

public class ReadFileTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {
        Path file = Paths.get("aioFile.txt");
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);

        ByteBuffer buffer = ByteBuffer.allocate(10);
        Future<Integer> result = channel.read(buffer, 0);

        while(! result.isDone()) { ProfitCalculator.calculateTax(); } Integer bytesRead = result.get(); System.out.println("Bytes read [" + bytesRead + "]"); }}class ProfitCalculator {
    public ProfitCalculator(a) {}public static void calculateTax(a) {}}Copy the code

summary

This article mainly introduces the basic concepts and understanding of synchronous/asynchronous, blocking/non-blocking, BIO, NIO, AIO.