Difference between standard IO and NIO -
The new input/output (NIO) library was introduced with JDK 1.4. Picking up where original I/O leaves off, NIO provides high-speed, block-oriented I/O in standard Java code. By defining classes to hold data, and by processing that data in blocks, NIO takes advantage of low-level optimizations in a way that the original I/O package could not, without using native code.Recalling old IO facility
I/O (input/output) refers to the interface between a computer and the rest of the world, or between a single program and the rest of the computer. Individual programs generally have most of their work done for them. In Java programming, I/O has until recently been carried out using a stream metaphor. All I/O is viewed as the movement of single bytes, one at a time, through an object called a Stream. Stream I/O is used for contacting the outside world. It is also used internally, for turning objects into bytes and then back into objects.Introducing NIO
NIO was created to allow Java programmers to implement high-speed I/O without having to write custom native code. NIO moves the most time-consuming I/O activities (namely, filling and draining buffers) back into the operating system, thus allowing for a great increase in speed.If above introductions have left you thirsty then don’t worry if you will feel bettor as we go forward. Let’s start by finding the differences.
Identifying differences between IO and NIO
1) IO streams versus NIO blocks
The most important distinction between the original I/O library (found in java.io.*) and NIO has to do with how data is packaged and transmitted. As previously mentioned, original I/O deals with data in streams, whereas NIO deals with data in blocks.A stream-oriented I/O system deals with data one or more bytes at a time. An input stream produces one byte of data, and an output stream consumes one byte of data. It is very easy to create filters for streamed data. It is also relatively simply to chain several filters together so that each one does its part in what amounts to a single, sophisticated processing mechanism. Important thing is that bytes are not cached anywhere. Furthermore, you cannot move forth and back in the data in a stream. If you need to move forth and back in the data read from a stream, you must cache it in a buffer first.
A block-oriented I/O system deals with data in blocks. Each operation produces or consumes a block of data in one step. Processing data by the block can
be much faster than processing it by the (streamed) byte. You can move forth and back in the buffer as you need to. This gives you a bit more flexibility during processing. However, you also need to check if the buffer contains all the data you need in order to fully process it. And, you need to make sure that when reading more data into the buffer, you do not overwrite data in the buffer you have not yet processed. But block-oriented I/O lacks some of the elegance and simplicity of stream-oriented I/O.
Read more: 3 ways to read files using Java NIO
2) Synchronous vs. Asynchronous IO
Java IO’s various streams are blocking or synchronous. That means, that when a thread invokes a read() or write(), that thread is blocked until there is some data to read, or the data is fully written. The thread will be in blocked state for this period. This has been cited as a good solid reason for bringing multi-threading in modern languages.In asynchronous IO, a thread can request that some data be written to a channel, but not wait for it to be fully written. The thread can then go on and do something else in the mean time. Usually these threads spend their idle time on when not blocked in IO calls, is usually performing IO on other channels in the meantime. That is, a single thread can now manage multiple channels of input and output.
Synchronous programs often have to resort to polling, or to the creation of many, many threads, to deal with lots of connections. With asynchronous I/O, you can listen for I/O events on an arbitrary number of channels, without polling and without extra threads.
The central object in asynchronous I/O is called the Selector. A Selector is where you register your interest in various I/O events, and it is the object that tells you when those events occur. So, the first thing we need to do is create a Selector:
1
|
Selector selector = Selector.open(); |
Read more: How to define Path in java NIO
3) IO Versus NIO APIs
No prize for guessing that the API calls when using NIO look different than when using IO. Here in NIO, rather than just read the data byte for byte from e.g. an InputStream, the data must first be read into a buffer, and then be processed from thereafter.Sample code using standard IO
Sample code using NIO
If you need to manage thousands of open connections simultaneously, which each only send a little data, for instance a chat server, implementing the server in NIO is probably an advantage. Similarly, if you need to keep a lot of open connections to other computers, e.g. in a P2P network, using a single thread to manage all of your outbound connections might be an advantage.
If you have fewer connections with very high bandwidth, sending a lot of data at a time, standard IO server implementation should be your choice.
Automatic resource management with try-with-resources in java 7
Java 7 has brought some very good features for lazy java developers. Try-with-resources is one of such feature which cuts line of code and also make the code more robust. In this tutorial, I will discuss things around this feature.The old way of resource cleanup (Before java 7)
We have been doing this from long time. e.g. read a file from file system. Code may look different but flow will be like below example:Code inside try and catch blocks are essentially important and have some application specific logics. But what about finally block?? Most of the time, finally blocks are just copy pasted for sake of saving the resources from corruption, by closing them.
These finally blocks looks more ugly, when you have 3-4 such resources to close in single finally block. Don’t you think these finally blocks are unnecessarily there when we know, we have to close the resource anyhow without any exceptional case??
Java 7 solves this problem with try-with-resources feature.
The new fancy way with try-with-resources (syntax example)
Now look at the new way of opening and closing a resource in java 7.- File resource (BufferedReader) is opened in try block in special manner (inside small brackets).
- Finally block is completely gone.
How actually it works?
In java 7, we have a new super interface java.lang.AutoCloseable. This interface have one method:
1
|
void
close() throws Exception; |
When we open any such AutoCloseable resource in special try-with-resource block, immediately after finishing the try block, JVM calls this close() method on all resources initialized in “try()” block.
For example, BufferedReader has implemented close() method file this:
Adding functionality to custom resources
Well, this is a good resource cleanup design. But is it available to JDK native classes only?? NO. You can use it also to your custom resources.For example, I have create a custom resource in below code:
public class CustomResource
implements AutoCloseable
{
public void accessResource()
{
System.out.println("Accessing
the resource");
}
@Override
public void close()
throws Exception {
System.out.println("CustomResource
closed automatically");
}
}
|
- Before java 7, we had to use finally blocks to cleanup the resources. Finally blocks were not mandatory, but resource clean up was to prevent the system from being corrupt.
- With java 7, no need to explicit resource cleanup. Its done automatically.
- Automatic resource cleanup done when initializing resource in try-with-resources block (try(…) {…}).
- Cleanup happens because of new interface AutoCloseable. Its close method is invoked by JVM as soon as try block finishes.
- If you want to use this in custom resources, then implementing AutoCloseable interface is mandatory. otherwise program will not compile.
- You are not supposed to call close() method in your code. This should be called automatically bu JVM. Calling it manually may cause unexpected results.
0 comments:
Post a Comment