Java NIO - AsynchronousFileChannel

Como sabemos, Java NIO admite concurrencia y subprocesos múltiples, lo que nos permite tratar con diferentes canales simultáneamente al mismo tiempo, por lo que la API responsable de esto en el paquete Java NIO es AsynchronousFileChannel, que se define en el paquete de canales NIO. para AsynchronousFileChannel es java.nio.channels.AsynchronousFileChannel.

AsynchronousFileChannel es similar al FileChannel de NIO, excepto que este canal permite que las operaciones de archivo se ejecuten de forma asíncrona a diferencia de la operación de E / S síncrona en la que un hilo entra en una acción y espera hasta que se completa la solicitud. Por lo tanto, los canales asíncronos son seguros para su uso. por múltiples subprocesos concurrentes.

En asincrónico, la solicitud se pasa por subproceso al kernel del sistema operativo para que se haga mientras el subproceso continúa procesando otro trabajo.Una vez que el trabajo del kernel está terminado, señala el subproceso, luego el subproceso reconoce la señal e interrumpe el trabajo actual y procesa Trabajo de E / S según sea necesario.

Para lograr la concurrencia, este canal proporciona dos enfoques que incluyen uno como devolución de un java.util.concurrent.Future object y otro es Pasar a la operación un objeto de tipo java.nio.channels.CompletionHandler.

Entenderemos ambos enfoques con la ayuda de ejemplos uno por uno.

  • Future Object - En este caso, se devuelve una instancia de Future Interface desde el canal. get() método que devuelve el estado de la operación que se maneja de forma asincrónica sobre la base del cual se podría decidir la ejecución adicional de otra tarea.También podemos verificar si la tarea se completó o no llamando a su isDone método.

Ejemplo

El siguiente ejemplo muestra cómo utilizar el objeto Future y la tarea de forma asincrónica.

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();
   }
}

Salida

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 -

    Este enfoque es bastante simple, ya que usamos la interfaz CompletionHandler y anula sus dos métodos, uno es completed() método que se invoca cuando la operación de E / S se completa correctamente y otro es failed() método que se invoca si fallan las operaciones de E / S. En este, se crea un controlador para consumir el resultado de una operación de E / S asíncrona, ya que una vez que se completa una tarea, solo el controlador tiene funciones que se ejecutan.

Ejemplo

El siguiente ejemplo muestra cómo utilizar CompletionHandler para realizar tareas de forma asincrónica.

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();
   }
}

Salida

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.