ation:
if (!future.isDone()) {
future.cancel(true);
}
Thecancel()method takes a boolean flag to indicate whether the thread performing the accept can be interrupted. This is a useful enhancement; in previous Java releases, blocking I/O operations like this could only be aborted by closing the socket.
Client setup
Next, we can set up the client by opening and connecting aAsynchronousSocketChannelto the server:
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
client.connect(server.getLocalAddress()).get();
Once the client is connected to the server, reads and writes can be performed via the channels using byte buffers, as shown in Listing 1:
Listing 1. Using byte buffers for reads and writes
// send a message to the server
ByteBuffer message = ByteBuffer.wrap("ping".getBytes());
client.write(message).get();
// read a message from the client
worker.read(readBuffer).get(10, TimeUnit.SECONDS);
System.out.println("Message: " + new String(readBuffer.array()));
Scattering reads and writes, which take an array of byte buffers, are also supported asynchronously.
The APIs of the new asynchronous channels completely abstract away from the underlying sockets: there's no way to obtain the socket directly, whereas previously you could callsocket()on, for example, aSocketChannel. Two new methods — getOptionandsetOption — have been introduced for querying and setting socket options in the asynchronous network channels. For example, the receive buffer size can be retrieved bychannel.getOption(StandardSocketOption.SO_RCVBUF)instead ofchannel.socket().getReceiveBufferSize();.
Completion handlers
The alternative mechanism to usingFutureobjects is to register a callback to the asynchronous operation. TheCompletionHandlerinterface has two methods:
void completed(V result, A attachment)executes if a task completes with a result of typeV.
void failed(Throwable e, A attachment)executes if the task fails to complete due toThrowable e.
The attachment parameter of both methods is an object that is passed in to the asynchronous operation. It can be used to track which operation finished if the same completion-handler object is used for multiple operations.
Open commands
Let's look at an example using theAsynchronousFileChannelclass. We can create a new channel by passing in ajava.nio.file.Pathobject to the staticopen()method:
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("myfile"));
Newopencommands forFileChannel
The format of the open commands for asynchronous channels has been backported to theFileChannelclass. Under NIO, aFileChannelis obtained by callinggetChannel()on aFileInputStream,FileOutputStream, orRandomAccessFile. With NIO.2, aFileChannelcan be created directly using anopen()method, as in the examples shown here.
Pathis a new class in Java 7 that we look at in more detail inPart 2. We use thePaths.get(String)utility method to create aPathfrom aStringrepresenting the filename.
By default, the file is opened for reading. Theopen()method can take additional options to specify how the file is opened. For example, this call opens a file for reading and writing, creates it if necessary, and tries to delete it when the channel is closed or when the JVM terminates:
fileChannel = AsynchronousFileChannel.open(Paths.get("afile"),
StandardOpenOption.READ, StandardOpenOption.WRITE,
StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE);
An alternativeopen()method provides finer control over the channel, allowing file attributes to be set.
Implementing a completion handler
Next, we want to write to the file and then, once the write has completed, execute something. We first construct aCompletionHandlerthat encapsulates the "something" as shown in Listing 2:
Listing 2. Creating a completion handler
CompletionHandler<Integer, Object> handler =
new CompletionHandler<Integer, Object>() {
@Override
public void completed(Integer result, Object attachment) {
System.out.println(attachment + " completed with " + result + " bytes written");
}
@Override
public void failed(Throwable e, Object attachment) {
System.err.println(attachment + " failed with:");
e.printStackTrace();
}
};
Now we can perform the write:
fileChannel.write(ByteBuffer.wrap(bytes), 0, "Write operation 1", handler);
Thewrite()method takes:
AByteBuffercontaining the contents to write
An absolute position in the file
An attachment object that is passed on to the completion handler methods
A completion handler
Operations must give an absolute position in the file to read to or write from. It doesn't make sense for the file to have an internal position marker and for reads/writes to occur from there, because the operations can be initiated before previous ones are completed and the order they occur in is not guaranteed. For the same reason, there are no methods in theAsynchronousFileChannelAPI that set or query the position, as there are inFileChannel.
In addition to the read and write methods, an asynchronous lock method is also supported, so that a file can be locked for exclusive access without having to block in the current thread (or poll usingtryLock) if another thread currently holds the lock.