During a weekend afternoon phone interview at home, I asked the candidates a few questions about IO, including what are BIO, NIO and AIO? What’s the difference between the three? How to use it, but the answers are not very satisfactory. So I wrote in my interview review, “I don’t have a deep understanding of Java IO reminders.” My girlfriend just happened to see me.

Java IO

IO, often written as I/O, is short for Input/Output, that is, Input/Output. Usually data is input and output between internal storage (memory) and external storage (hard disk, usb disk, etc.) or other peripheral devices.

Input/output is the communication between an information processing system, such as a computer, and the outside world, which may be a human or another information processing system.

Inputs are signals or data received by the system and outputs are signals or data sent from it.

In Java, a series of apis are provided for developers to read and write external data or files. We call these apis Java IO.

IO is an important and difficult knowledge in Java, mainly because with the development of Java, there are currently three KINDS of IO. They are BIO, NIO and AIO.

Java BIO

BIO block-IO is a synchronous and blocking communication mode. Is a more traditional communication mode, simple mode, easy to use. However, the concurrent processing capacity is low, communication time is time-consuming, and network speed is dependent.

Java NIO

Java NIO, full non-block IO, is a new feature optimized for network transport performance since Java SE version 1.4. Is a non-blocking synchronous communication mode.

NIO has the same role and purpose as original I/O, but the most important difference between them is the way data is packaged and transferred. Whereas the original I/O processed data as a stream, NIO processed data as a block.

Stream-oriented I/O systems process data one byte at a time. An input stream produces one byte of data, and an output stream consumes one byte of data.

Block-oriented I/O systems process data as blocks. Each operation generates or consumes a block of data in a step. Processing data in chunks is much faster than processing data in (streaming) bytes. But block-oriented I/O lacks some of the elegance and simplicity of stream-oriented I/O.

Java AIO

Java AIO, Asynchronous Asynchronous IO, is Asynchronous non-blocking IO. Is a non-blocking asynchronous communication mode.

A new concept of asynchronous channels is introduced based on NIO, and an implementation of asynchronous file channels and asynchronous socket channels is provided.

Three IO differences

First, let’s take the big picture and redraw the key points:

BIO (Blocking I/O) : synchronously Blocking I/O mode.

NIO (New I/O) : Synchronous non-blocking mode.

AIO (Asynchronous I/O) : Asynchronous non-blocking I/O model.

So what about synchronous blocking, synchronous non-blocking, and asynchronous non-blocking? You can also see this section in Ramble: How to Explain Blocking, Non-blocking, Synchronous, and Asynchronous in IO to Your Girlfriend. .

Synchronous blocking mode: In this mode, we go to the kitchen, start boiling water, and sit in front of the kettle waiting for the water to boil.

Synchronous non-blocking mode: In this mode, we go to the kitchen and start boiling water, but instead of sitting in front of the kettle, we go back to the living room to watch TV, and then come to the kitchen every few minutes to check if the water is boiling.

Asynchronous non-blocking I/O model: In this mode, we go to the kitchen first and start boiling water. Instead of sitting in front of the kettle and waiting, or checking it every once in a while, we watch TV in the living room. There’s a switch on the kettle and it tells me when the water is boiling.

Blocking VS non-blocking: does the person sit in front of the kettle and wait?

Synchronous VS asynchronous: does the kettle inform the person when the water is boiling?

Applicable scenario

BIO mode is suitable for small and fixed number of connections. This mode requires high server resources, concurrency is limited to the application, and the only choice before JDK1.4, but the program is intuitive, simple and easy to understand.

NIO is suitable for architectures with a large number of connections and relatively short (light operation) connections, such as chat servers, where concurrency is limited to applications and programming is complicated. JDK1.4 supports NIO.

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

use

Use BIO to read and write files.

//Initializes The Object
User1 user = new User1();
user.setName("hollis");
user.setAge(23);
System.out.println(user);

//Write Obj to File
ObjectOutputStream oos = null;
try {
    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
    oos.writeObject(user);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    IOUtils.closeQuietly(oos);
}

//Read Obj from File
File file = new File("tempFile");
ObjectInputStream ois = null;
try {
    ois = new ObjectInputStream(new FileInputStream(file));
    User1 newUser = (User1) ois.readObject();
    System.out.println(newUser);
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} finally {
    IOUtils.closeQuietly(ois);
    try {
        FileUtils.forceDelete(file);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//Initializes The Object
User1 user = new User1();
user.setName("hollis");
user.setAge(23);
System.out.println(user);

//Write Obj to File
ObjectOutputStream oos = null;
try {
    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
    oos.writeObject(user);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    IOUtils.closeQuietly(oos);
}

//Read Obj from File
File file = new File("tempFile"); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(file)); User1 newUser = (User1) ois.readObject(); System.out.println(newUser); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(ois); try { FileUtils.forceDelete(file); } catch (IOException e) { e.printStackTrace(); }}Copy the code

NIO is used to read and write files.

static void readNIO() {
        String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(new File(pathname));
            FileChannel channel = fin.getChannel();

            int capacity = 100;// 字节
            ByteBuffer bf = ByteBuffer.allocate(capacity);
            int length = -1;

            while((length = channel.read(bf)) ! = -1) { bf.clear(); byte[] bytes = bf.array(); System.out.write(bytes, 0, length); System.out.println(); } channel.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally {if(fin ! = null) { try { fin.close(); } catch (IOException e) { e.printStackTrace(); } } } } static voidwriteNIO() {
        String filename = "out.txt";
        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream(new File(filename));
            FileChannel channel = fos.getChannel();
            ByteBuffer src = Charset.forName("utf8").encode("Hello hello hello hello hello hello");
            int length = 0;

            while((length = channel.write(src)) ! = 0) { System.out.println("Write length :" + length);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fos ! = null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); }}}}Copy the code

AIO is used to read and write files

public class ReadFromFile {
  public static void main(String[] args) throws Exception {
    Path file = Paths.get("/usr/a.txt");
    AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);

    ByteBuffer buffer = ByteBuffer.allocate(100_000);
    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() {
  }
  public static void calculateTax() {
  }
}

public class WriteToFile {

  public static void main(String[] args) throws Exception {
    AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
        Paths.get("/asynchronous.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

Drip, drip, the water is boiling.