NIO vs IO in Java

Summary

Java NIO, introduced in Java 1.4, provides a non-blocking, buffer-oriented approach to I/O, contrasting with traditional blocking, stream-oriented Java IO. Unlike IO which processes data byte-by-byte, NIO reads into flexible buffers, allowing pointer manipulation and enabling threads to perform other tasks during I/O operations. A key feature of NIO is the Selector, which allows a single thread to efficiently monitor multiple channels, significantly reducing the number of threads required for high-concurrency applications. This design necessitates different data processing strategies, as NIO requires explicit checks for complete data reception, but ultimately allows for more scalable and resource-efficient system architectures compared to IO's suitability for fewer, larger data transfers.

Java 1.4 provides a new API for handling IO -- NIO. This is a non-blocking and buffer oriented IO API.

Below are main differences between the NIO and IO in Java.

IO NIO
Stream oriented Buffer oriented
Blocking IO Non-blocking IO
N/A Using selector

Stream oriented vs Buffer oriented

The main difference is that IO is stream oriented where the data is read byte by byte and the data will not be buffered normally.This means there is no pointer to move forward and backward in the stream. If there is a need to move forward and backward of the stream, the data needs to be explicitly copied to a buffer. While Java NIO will read data into a buffer area which will be processed later. There is pointer to move forward and backward of the buffer area. This increases the flexibility. One thing to note is that some check needs to be enforced when trying to process the data to see whether it contains all data to be processed or the data is overwritten.

Blocking vs Non-blocking

Java IO is blocking. This means the thread will be blocking if it is calling read() or write(). The thread will be unblocked until the read or write operation is completed. Java NIO is non-blocking, it will read the data through channels and it can only read the data available at the channel while the read operation occurs. If there is no data at the channel, then no data will be read and the thread continues. This design can allow the thread to do other things while the read operation is going on. This further enables a single thread to monitor multiple input and output channels.

Selectors

Java NIO selectors allow a single thread to monitor multiple input channels. You can register multiple channels to use the same selector. This will reduce the number of threads needed which are resource consuming.

How NIO and IO can affect application design

No matter NIO or IO is chosen, following aspects of application design may be affected.

  1. The call to NIO and IO API
  2. Data processing
  3. Threads to process data

API call

Apparently NIO and IO will use different implementations since they have different design principles.

Data processing

In IO design, when reading data from InputStream or Reader, the data is read byte by byte. Assuming you are handling below input data:

Name: Anna
Age: 25
Email: [email protected]
Phone: 1234567890

The data may be handled in following way when using IO.

BufferedReader reader = new BufferedReader(new InputStreamReader(input));

String nameLine   = reader.readLine();
String ageLine    = reader.readLine();
String emailLine  = reader.readLine();
String phoneLine  = reader.readLine();

The processing state will be determined the read and write calls return. You will know that the data is read if the readLine(0 method returns. Since it's blocking, each line will be read one by one and when all readLine() operations complete, the data is completely read.

While using NIO, below code is needed.

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

In the second line, the data will be read to buffer. But since NIO is non-blocking, there is no guarantee that the data is completely read while read() returns. This increases the difficulty to determine whether the data is completely read. Below code may be needed to check whether data is completely read.

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

while(! bufferFull(bytesRead) ) {

bytesRead = inChannel.read(buffer);

}

Below diagram shows how to process data using NIO.

Thread number

NIO will need far less threads to process data than IO given the fact it is non-blocking and t uses selectors. A single thread or a few threads can process lots of channels. If you are developing chat server or P2P application, NIO may be desired.

IO is suitable for sending large chunk of data once and if the connection number is small. Below is a classical server design with IO API.

Reference : http://www.codeceo.com/article/java-nio-io.html

JAVA IO NIO

  RELATED

  COMMENTS

0

No comment for this article.