Introduction to the

Do you still remember our original intention of using IO and NIO?

Brother F, don’t you use IO and NIO to make life better and the world full of love? Let us programmers gracefully move data from one place to another. Sharpen your tools and do good things so you have more time to enjoy life.

Good, if you compare data to people, the purpose of IO NIO is to transport people to the United States.

Brother F, why should they be shipped to The United States? The coronavirus is too serious in the United States. I’d better stay in China. China is the safest country in the world!

Well, just to be on the safe side, we’ll ship them to Shanghai. People are data. How do you get there? You can take a plane, you can take a car, you can take a train, you can take a plane, you can take a car, you can take a train as a Buffer.

Finally, the flight path of an airplane, the road of a car and the track of a train can be regarded as channels one by one.

More highlights:

  • Blockchain from getting started to Giving up series tutorials – with ongoing updates covering cryptography, Hyperledger, Ethereum,Libra, Bitcoin and more
  • Spring Boot 2.X Series tutorials: Learn Spring Boot from Scratch in seven days – continuous updates
  • Spring 5.X Series tutorials: Everything you can think of in Spring5 – constantly updated
  • Java Programmer from Handyman to Expert to God (2020 edition) – Ongoing updates with detailed articles and tutorials

Simply put, a channel is a channel that transports buffers.

IO can be divided into two types by source: File IO from a File and Stream IO from a Stream. Regardless of the IO, data can be transported through channels.

The classification of the Channel

There are only two sources of data, but there are many classes of channels in the JDK, as shown in the following figure:

Let’s start with the most basic and top-level interface, Channel:

public interface Channel extends Closeable {
    public boolean isOpen(a);
    public void close(a) throws IOException;

}
Copy the code

The top-level Channel is simple, inheriting the Closeable interface and implementing two methods isOpen and close.

One is used to determine whether a channel is open and one is used to close a channel.

Brother F, how come the top-level Channel is so simple? It doesn’t fit the complicated design of Channel.

Don’t worry, it makes sense for the JDK to do this, because the top-level interface has to be more abstract and generic, and as a result, it turns out that there are really only two methods that are generic.

So to deal with this problem, there are many different types defined in channels.

The lowest level Channel has five types:

FileChannel

The FileChannel that is associated with File is one of the five channels.

FileChannel can be obtained from RandomAccessFile, FileInputStream, or FileOutputStream by calling getChannel().

You can also pass in the Path creation directly by calling the open method in FileChannel.

public abstract class FileChannel
    extends AbstractInterruptibleChannel
    implements SeekableByteChannel.GatheringByteChannel.ScatteringByteChannel
Copy the code

Let’s look at the interfaces and classes that FileChannel inherits or implements.

AbstractInterruptibleChannel implements InterruptibleChannel interface, interrupt is known to all, used to interrupt thread execution tool. Let’s take a look at some very cryptic code:

protected final void begin(a) {
        if (interruptor == null) {
            interruptor = new Interruptible() {
                    public void interrupt(Thread target) {
                        synchronized (closeLock) {
                            if (closed)
                                return;
                            closed = true;
                            interrupted = target;
                            try {
                                AbstractInterruptibleChannel.this.implCloseChannel();
                            } catch (IOException x) { }
                        }
                    }};
        }
        blockedOn(interruptor);
        Thread me = Thread.currentThread();
        if (me.isInterrupted())
            interruptor.interrupt(me);
    }
Copy the code

The code above is AbstractInterruptibleChannel core.

We first define an instance of Interruptible with an interrupt method that closes a Channel.

It then gets an instance of the current thread, checks if the current thread is Interrupted, and calls Interruptible interrupt to close the current channel.

SeekableByteChannel Connects entries or files. It has a unique property called position, which represents the current reading position. It can be modified.

GatheringByteChannel and ScatteringByteChannel indicate that a combination of Buffer sequences can be read and written one at a time:

public long write(ByteBuffer[] srcs, int offset, int length)
        throws IOException;
public long read(ByteBuffer[] dsts, int offset, int length)
        throws IOException;
Copy the code

The Selector and the Channel

Before we talk about the other channels, let’s look at a Selector associated with the following channels:

There is a new Channel type called SelectableChannel. The previous FileChannel connection was one-to-one, meaning that a Channel has to correspond to one thread of processing. SelectableChannel, on the other hand, is one-to-many, which means that a single processing thread can handle multiple channels with a Selector.

SelectableChannel monitors multiple channels by registering different selectionkeys. We’ll talk more about using Selector later, so stay tuned.

DatagramChannel

DatagramChannel is a Channel used to process UDP. It comes with the Open method to create instances.

Let’s look at the definition of DatagramChannel:

public abstract class DatagramChannel
    extends AbstractSelectableChannel
    implements ByteChannel.ScatteringByteChannel.GatheringByteChannel.MulticastChannel
Copy the code

ByteChannel indicates that it is both a ReadableByteChannel and a WritableByteChannel, which can write and read at the same time.

MulticastChannel represents a multicast protocol. This corresponds to UDP.

SocketChannel

SocketChannel is a channel used to process TCP. It is also created using the Open method.

public abstract class SocketChannel
    extends AbstractSelectableChannel
    implements ByteChannel.ScatteringByteChannel.GatheringByteChannel.NetworkChannel
Copy the code

The only difference between SocketChannel and DatagramChannel is that the NetworkChannel excuse is implemented.

NetworkChannel provides network socket operations, such as binding addresses.

ServerSocketChannel

ServerSocketChannel is also a NetworkChannel that is used to listen on the server side.

public abstract class ServerSocketChannel
    extends AbstractSelectableChannel
    implements NetworkChannel
Copy the code

AsynchronousSocketChannel

The last AsynchronousSocketChannel is an asynchronous Channel:

public abstract class AsynchronousSocketChannel
    implements AsynchronousByteChannel.NetworkChannel
Copy the code

Why asynchronous? Let’s look at one method:

public abstract Future<Integer> read(ByteBuffer dst);
Copy the code

As you can see, the return value is a Future, so the read method can return immediately and only take the value from the Future if we need it.

The use of the Channel

Brother F, I am dazzled by so many kinds of channels. Can you give me a specific example of Channel?

The transferTo method can be used to copy files easily. However, in order to see the common use of Channel, we choose a more general example:

public void useChannelCopy(a) throws IOException {
        FileInputStream input = new FileInputStream ("src/main/resources/www.flydean.com");
        FileOutputStream output = new FileOutputStream ("src/main/resources/www.flydean.com.txt");
        try(ReadableByteChannel source = input.getChannel(); WritableByteChannel dest = output.getChannel()){
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            while(source.read(buffer) ! = -1)
            {
                // flip buffer, ready to write
                buffer.flip();
                // See if there is more content
                while (buffer.hasRemaining())
                {
                    dest.write(buffer);
                }
                // Clear buffer, for next usebuffer.clear(); }}}Copy the code

In the example above we read Buffer from InputStream and write it to FileOutputStream.

conclusion

Today we explained the specific classification of channels and a simple example. Later we will experience other examples of channels. Please look forward to them.

Examples of this article github.com/ddean2009/l…

Author: Flydean program stuff

Link to this article: www.flydean.com/java-io-nio…

Source: Flydean’s blog

Welcome to pay attention to my public number: procedures those things, more wonderful waiting for you!