Non-Blocking I/O Made Possible in Java
NIO.2 Features in JDK 1.7
In this section we will cover some of the features of NIO.2 from the perspective of this article:
- An abstraction of a file system - java.nio.file
- Enhancements to java.io.channels
- asynchronous I/O
java.nio.file
Typical operations such as deleting, copying and moving files are supported, as well as file access permission retrieval and existence checking. Metadata about the files themselves and the file stores in which they reside are provided. Improved file I/O capabilities include channel- based I/O and directory operations (including create, delete and read). Where supported by the host operating system, the creation of UNIX-style symbolic and hard links is supported. An interesting capability to recursively walk a directory tree is provided as well as locating sets of files matching a specific filename pattern specified by a UNIX shell-style glob or regular expression.
The capabilities of this package are dependent upon the semantics of the host operating system.
Below is an example of using java.nio.file.Path to open a file as a Channel:
FileSystem fileSystem = FileSystems.getDefault(); Path file1 = fileSystem.getPath("C:/TestFileChannel.java"); FileChannel fcin = FileChannel.open(file1);
An Updated java.nio.channels
SeekableByteChannel (New Addition)
- Maintains a current file position.
- Factory methods such as newByteChannel(…)
- Methods to read and write to the channel using ByteBuffer
FileChannel (Updated)
- Implements SeekableByteChannel
- New
open()
methods to open a file with Channel semantics.
NetworkChannel (New Addition)
- Represents a network socket and defines methods for binding, setting socket options and returning local addresses.
ServerSocketChannel / SocketChannel / DatagramChannel (Updated)
- Each of the network oriented channels implements NetworkChannel
- Methods related to binding and connecting have been added without requiring
socket()
- Multicast support has been added to DatagramChannel
Asynchronous I/O for Sockets and Files
AsynchronousChannel
A channel that supports asynchronous I/O operations.
AsynchronousByteChannel
An asynchronous channel that can read and write bytes.
AsynchronousFileChannel
An asynchronous channel for reading, writing, and manipulating a file without support for a current file position (i.e. not seekable). You could specify the file position to each read and write operation.
AsynchronousSocketChannel
An asynchronous channel for connection oriented network client-sockets (TCP) with timeout on read/write operations.
AsynchronousDatagramChannel
An asynchronous channel for datagram-oriented sockets with a support for multicasting.
AsynchronousServerSocketChannel
An asynchronous channel for stream-oriented listening sockets.
CompletionHandler
A handler for consuming the result of an asynchronous I/O operation as call back methods: cancelled(), completed(), failed()
. The caller supplies the implementation for each call back (avoid long lived and blocking operations inside these methods).
AsynchronousChannelGroup
A grouping of asynchronous channels for the purpose of resource sharing (i.e. thread pools). Asynchronous channels that do not specify a group at construction time are bound to the default group maintained by JVM.
Using Asynchronous IO API
The Asynchronous IO is initiated with java.util.concurrent
specific classes to implement robust and scalable Network IO components. Following code snippet demonstrates how to create an AsychronousChannelGroup
using java.util.concurrent.ExecutorService
that leverages N number of threads (fixed thread pool).
//Use java.util.concurrent.Executor to run the tasks submitted //creating an an asynchronous channel group with a fixed thread pool. java.util.concurrent.ExecutorService executor = Executors.newFixedThreadPool(poolSize); AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(executor);
An Asynchronous channel could be a part of a group of could exist independently (part of default group maintained by JVM). Following code snippet demonstrates how to use create an AsynchronousChannel
both ways - part of a group or part of a default group.
//create channels as a part of a group AsynchronousServerSocketChannel asynServer = AsynchronousServerSocketChannel.open(group); AsynchronousSocketChannel asyChannel = AsynchronousSocketChannel.open(group); //create channels as part of a default group final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
There are two ways you could accomplish or initiate non-blocking asynchronous IO: Using java.util.concurrent
package or using java.nio.channels.CompletionHandler
.
Following code snippet demonstrates use of java.util.concurrent
specific classes.
//Use java.util.concurrent package to accomplish non-blocking I/O ByteBuffer buffer = ByteBuffer.allocate(1024); java.util.concurrent.Future<Integer> pendingResult = asyChannel.read(buffer); int nReads = pendingResult.get(); //wait for the I/O to complete boolean isDone = pendingResult.isDone();
Following code snippet demonstrates use of java.nio.channels.CompletionHandler
.
//Use completion Handler to accomplish non-blocking I/O listener.accept(null, new CompletionHandler<ASYNCHRONOUSSOCKETCHANNEL,VOID>() { public void completed(AsynchronousSocketChannel ch, Void att) { handleAccept(ch); // handle next connection Future<ASYNCHRONOUSSOCKETCHANNEL> asySocCh = listener.accept(null, this); } public void failed(Throwable exc, Void att) { // handleFailed(); } public void cancelled(Void att) { // handleCancelled(); } …….. }
Resources
NIO Java Specification
NIO.2 Java Specification
Reactor Pattern - Implementing Selector
NIO.2 Examples
Article on Concurrent processing
An Introduction to Java NIO and NIO.2
Java One Presentation on Asynchronous IO
JSR 203 Spec Discussion
Page 3 of 3
This article was originally published on September 16, 2009