“This is the 12th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

Java NIO (New IO or Non Bloking IO) is a New IO API introduced from Java version 1.4 that replaces the standard Java IO API. NIO fully supports buffer-oriented, channel-based IO operations. NIO will read and write files in an efficient manner.

Blocking IO

Typically during synchronous I/O operations, if data is read, the code blocks until there is data available to read. Similarly, the write call will block until the data can be written. The traditional Server/Client mode is based on Thread per Request (TPR). The Server creates a Thread for each Client Request, and the Thread is solely responsible for processing a Client Request. The problem with this pattern is the rapid increase in the number of threads, which increases the overhead of the service. Most implementations avoid this problem by using the thread pool model and setting the maximum number of thread pools. This introduces a new problem. If there are 100 threads in the thread pool and 100 users are downloading large files, 101 users’ requests will not be processed in a timely manner. Even if the 101st user points to a page several kilobytes in size. The traditional Server /Client mode is shown in the following figure

Non-blocking IO (NIO)

NIO uses a Reactor pattern-based approach for non-blocking I/O. I/O calls are not blocked, but instead register I/O events of interest, such as the arrival of readable data, new socket connections, and so on, and the system notifies us when certain events occur. The core object in NIO that implements non-blocking I/O is Selector.

Selector registers various I/O times and places, and when an event of interest occurs, it is this object that tells us what happened, as shown in the following figure:

As you can see from the diagram, when any registration event such as a read or write occurs, we get the SelectionKey of the response from the Selector, A colleague maliciously finds the event and the specific SelectableCannel from the SelectorKey to obtain the data sent by the client.

Non-blocking means that the IO itself does not block, but the select() method that gets the IO event does block and wait. NIO blocks event fetch. If there is no event, there is no I/O. At a high level, I/O is not blocking, that is to say, I/O is not blocking until the I/O has occurred. What about IO blocking? The nature of NIO is to delay IO operations until they actually happen, rather than waiting for IO operations whenever the IO stream is open.

Summary: NIO does not block after I/O is opened, but handles it when I/O occurs, which is essentially an I/O delay blocking.

IO NIO
Stream Oriented Buffer Oriented
Blocking IO (Blocking IO) Non-blocking IO
(not) Selector

NIO overview

Java NIO consists of the following core parts:

  • Channels
  • Buffers
  • Selectors

While there are many other classes and components in Java NIO, single channels, buffers, and selectors form the core API. Other components, such as Pipe and FileLock, are simply utility classes that work with the three core components.

Channel

A Channel is on the same level as a Stream of IO. Only the Stream is one-way, such as InputStream, OutputStream. A Channel is bidirectional and can be used for both read and write operations.

NIO implementations of channels include FileChannel, DatagramChannel, SocketChannel, and ServerSocketChannel. They correspond to file IO, UDP, and TCP (Server and Client) respectively.

Buffer

NIO finds that the key Buffer implementation is: ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBUffer, respectively corresponding to the basic data types: byte , char , dubbole, float , int , long , short.

Selector

Selector runs a single thread that handles multiple channels, and it can be handy if you have multiple channels open in your reference, but the traffic per connection is low, for example in a chat server, to use a Selector, You need to register a Channel with the Selector and then call the select() method. This method blocks until its registered channel is event-ready. Once the method returns, the thread can handle events such as new connections, data reception, and so on.