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.
- The call to NIO and IO API
- Data processing
- 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: anna@mailserver.com 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