Java NIO - AsynchronousFileChannel


Advertisements

As we know that Java NIO supports concurrency and multi-threading which allows us to deal with different channels concurrently at same time.So the API which is responsible for this in Java NIO package is AsynchronousFileChannel which is defined under NIO channels package.Hence qualified name for AsynchronousFileChannel is java.nio.channels.AsynchronousFileChannel.

AsynchronousFileChannel is similar to that of the NIO's FileChannel,except that this channel enables file operations to execute asynchronously unlike of synchronous I/O operation in which a thread enters into an action and waits until the request is completed.Thus asynchronous channels are safe for use by multiple concurrent threads.

In asynchronous the request is passed by thread to the operating system's kernel to get it done while thread continues to process another job.Once the job of kernel is done it signals the thread then the thread acknowledged the signal and interrupts the current job and processes the I/O job as needed.

For achieving concurrency this channel provides two approaches which includes one as returning a java.util.concurrent.Future object and other is Passing to the operation an object of type java.nio.channels.CompletionHandler.

We will understand both the approaches with help of examples one by one.

  • Future Object − In this an instance of Future Interface is returned from channel.In Future interface there is get() method which returns the status of operation that is handled asynchronously on the basis of which further execution of other task could get decided.We can also check whether task is completed or not by calling its isDone method.

Example

The following example shows the how to use Future object and to task asynchronously.

package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class FutureObject {
   public static void main(String[] args) throws Exception {
      readFile();
   }
   private static void readFile() throws IOException, InterruptedException, ExecutionException {
      String filePath = "D:fileCopy.txt";
      printFileContents(filePath);
      Path path = Paths.get(filePath);		
      AsynchronousFileChannel channel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);
      ByteBuffer buffer = ByteBuffer.allocate(400);
      Future<Integer> result = channel.read(buffer, 0); // position = 0
      while (! result.isDone()) {
         System.out.println("Task of reading file is in progress asynchronously.");
      }
      System.out.println("Reading done: " + result.isDone());
      System.out.println("Bytes read from file: " + result.get()); 
      buffer.flip();
      System.out.print("Buffer contents: ");
      while (buffer.hasRemaining()) {
         System.out.print((char) buffer.get());                
      }
      System.out.println(" ");
      buffer.clear();
      channel.close();
   }
   private static 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();
   }
}

Output

File contents: 
   To be or not to be?
   Task of reading file is in progress asynchronously.
   Task of reading file is in progress asynchronously.
   Reading done: true
   Bytes read from file: 19
   Buffer contents: To be or not to be? 
  • Completion Handler

    This approach is pretty simple as in this we uses CompletionHandler interface and overrides its two methods one is completed() method which is invoked when the I/O operation completes successfully and other is failed() method which is invoked if the I/O operations fails.In this a handler is created for consuming the result of an asynchronous I/O operation as once a task is completed then only the handler has functions that are executed.

Example

The following example shows the how to use CompletionHandler to task asynchronously.

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

public class CompletionHandlerDemo {
   public static void main (String [] args) throws Exception {
      writeFile();
   }
   private static void writeFile() throws IOException {
      String input = "Content to be written to the file.";
      System.out.println("Input string: " + input);
      byte [] byteArray = input.getBytes();
      ByteBuffer buffer = ByteBuffer.wrap(byteArray);
      Path path = Paths.get("D:fileCopy.txt");
      AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
      CompletionHandler handler = new CompletionHandler() {
         @Override
         public void completed(Object result, Object attachment) {
            System.out.println(attachment + " completed and " + result + " bytes are written.");
         }
         @Override
         public void failed(Throwable exc, Object attachment) {
            System.out.println(attachment + " failed with exception:");
            exc.printStackTrace();
         }
      };
      channel.write(buffer, 0, "Async Task", handler);
      channel.close();
      printFileContents(path.toString());
   }
   private static 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();
   }
}

Output

Input string: Content to be written to the file.
Async Task completed and 34 bytes are written.
File contents: 
Content to be written to the file.
Advertisements