CompletionHandler

java.nio.channels.CompletionHandler Example

This article introduces the CompletionHandler and its basic usage. This interface is available since Java SE 7 as part of Java NIO 2 File API. This article’s example shows reading from a file using asynchronous file channel and using the completion handler to consume its result.

The example in this article is compiled and run in Windows OS environment. Note that Java SE 7 is required to run the code.
 
 
 
 
 
 

1. Introduction

CompletionHandler<V,A> interface is defined in the java.nio.channels package.

The type parameters:

  • V – The result type of the I/O operation
  • A – The type of the object attached to the I/O operation

This is a handler for consuming the result of an asynchronous I/O operation.

The asynchronous channels (AsynchronousFileChannel, AsynchronousServerSocketChannel and AsynchronousSocketChannel) defined in the java.nio.channels package allow a completion handler to be specified to consume the result of an asynchronous operation. The handler is used as a mechanism for monitoring the initiated asynchronous I/O operations. The handler is specified as a parameter and is invoked to consume the result of the I/O operation (read or write).

This interface has two methods to override. The completed() method is invoked when the I/O operation completes successfully. The failed() method is invoked if the I/O operations fails.

The example in this article shows the usage of a completion handler with asynchronous file channel’s read operation.

2. Read Operation with Completion Handler

In this example a text file is read using an asynchronous file channel and the result is consumed by a completion handler.

2.1. The input file

This is an existing text file.

String filePath = "readfile.txt";
Path path = Paths.get(filePath);

2.2. Create a channel

The AsynchronousFileChannel.open() static method is used to create the channel. The method opens the file that is supplied to this method. By default the file is opened for read operation. The method throws IOException.

AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);

2.3. Create a buffer

Create a buffer using the ByteBuffer‘s allocate() static method, with initial capacity set to 1024.

ByteBuffer buffer = ByteBuffer.allocate(1024);

2.4. Read from the channel into the buffer

This explains the channel’s read operation and the consumption of its result by a completion handler.

AsynchronousFileChannel‘s read() method initiates an asynchronous read operation to read a sequence of bytes from this channel into the given buffer. The handler parameter is a completion handler that is invoked when the read operation completes (or fails). The result passed to the completion handler is the number of bytes read or -1 if no bytes could be read because the channel has reached end-of-stream.

The method doesn’t throw any checked exceptions.

currentThread = Thread.currentThread();

channel.read(buffer, 0, "Read operation ALFA", 
    new CompletionHandler() {
        @Override
        public void completed(Integer result, Object attachment) { 
            System.out.println(attachment + " completed and " + result + " bytes are read. ");
            currentThread.interrupt();
        } 
        @Override
        public void failed(Throwable e, Object attachment) {
            System.out.println(attachment + " failed with exception:");
            e.printStackTrace();
            currentThread.interrupt();
        }
});

try {
    currentThread.join();
}
...

Note, in the above code snippet, Thread class’s currentThread() static method returns the currently executing thread. In this case, the value (Thread.getName()) will be the main – that is the application’s main thread.

The channel’s read() method parameters are:

  • The buffer is the byte buffer into which the file contents are read
  • The value 0 is the position from where the file’s data transfer starts
  • “Read operation ALFA” is a String attachment object passed on to the completion handler methods
  • The completion handler for consuming the result

The channel’s read() method is invoked asynchronously. The read operation runs, completes and one of the completion handler methods is executed.

The Thread‘s join() method blocks the current thread (main), until interrupted. The handler’s methods execute the initiating thread’s (main) interrupt() method. This will make the main thread’s state runnable again.

2.5. Print the buffer contents

After the read operation the buffer’s position value is the number of bytes read. The buffer’s flip() method sets the position to zero.

buffer.flip();

while (buffer.hasRemaining()) {
				
    System.out.print((char) buffer.get());                
}

2.6. Clear buffer and close

The buffer’s clear() method makes a buffer ready for a new sequence of channel-read: It sets the limit to the capacity and the position to zero.

buffer.clear();
channel.close();

The channel’s close() method closes this channel. This method throws IOException.

3. The Code and the Output

The following is the complete code for the example showing the reading from a file using asynchronous file channel, and using a completion handler to consume the result of the read operation.

ReadExample.java

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.io.FileReader;
import java.io.BufferedReader;


public class ReadExample {
	
    private Thread currentThread;

    public static void main (String [] args)
            throws Exception {
	
        new ReadExample().readFile();
    }
	
    private void readFile()
            throws IOException {
	
        String filePath = "readfile.txt";
        printFileContents(filePath);
        Path path = Paths.get(filePath);
		
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
		
        ByteBuffer buffer = ByteBuffer.allocate(1024);
		
        currentThread = Thread.currentThread();
		
        channel.read(buffer, 0, "Read operation ALFA",
            new CompletionHandler() {
                @Override
                public void completed(Integer result, Object attachment) { 
                    System.out.println(attachment + " completed and " + result + " bytes are read. ");
                    currentThread.interrupt();
                } 
                @Override
                public void failed(Throwable e, Object attachment) {
                    System.out.println(attachment + " failed with exception:");
                    e.printStackTrace();
                    currentThread.interrupt();
                }
        });
		
        System.out.println ("Waiting for completion...");

        try {
            currentThread.join();
        }
        catch (InterruptedException e) {
        }

        buffer.flip();
		
        System.out.print("Buffer contents: ");
		
        while (buffer.hasRemaining()) {
				
            System.out.print((char) buffer.get());                
        }
        System.out.println(" ");
		
        buffer.clear();
        channel.close();
    }
	
    private void printFileContents(String path)
            throws IOException {

        FileReader fr = new FileReader(path);
        BufferedReader br = new BufferedReader(fr);
		
        String textRead = br.readLine();
        System.out.println("File contents: ");
		
        while (textRead != null) {
		
            System.out.println("     " + textRead);
            textRead = br.readLine();
        }
		
        fr.close();
        br.close();
    }
}

The output is:

File contents: All the way from the inquisitive solarium on the top floor to the garrulous kitchen in the basement, little groups - convalescents in wheeled chairs, nurses with tardy trays, lean internes on rubber soles, grizzled orderlies trailing damp mops - met to whisper and separated to disseminate the bad news. Doctor Hudson was on the verge of a collapse.
     *
Waiting for completion...

Read operation ALFA completed and 352 bytes are read.

Buffer contents: All the way from the inquisitive solarium on the top floor to the garrulous kitchen in the basement, little groups - convalescents in wheeled chairs, nurses with tardy trays, lean internes on rubber soles, grizzled orderlies trailing damp mops - met to whisper and separated to disseminate the bad news. Doctor Hudson was on the verge of a collapse.
*

From the output:

  • File contents: … This is the text in the file.
  • Waiting for completion… This is displayed while the file read is in progress.
  • Read operation ALFA completed and 352 bytes are read. The channel’s read operation is complete and the completion handler’s completed() method runs.
  • Buffer contents: All the way from the inquisitive solarium … The bytes in the buffer. Note this is the same as the file contents. The file had 352 bytes of text, and the buffer size was 1024. All the file contents are read in one read.

NOTES

See section 4 of the article java.nio.channels.AsynchronousFileChannel Example for the usage of completion handler with the asynchronous write operation.

4. Download Java Source Code

This was an example of java.nio.channels.CompletionHandler

Download
You can download the full source code of this example here: CompletionHandlerExample.zip

Prasad Saya

Prasad Saya is a software engineer with over ten years’ experience in application development, maintenance, testing and consulting on various platforms. He is a certified Java and Java EE developer. At present his interest is in developing Java applications. He also has experience working with databases and ERP applications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button