Java NIO - FileLock

Como sabemos, Java NIO admite concurrencia y subprocesos múltiples, lo que le permite lidiar con los subprocesos múltiples que operan en varios archivos al mismo tiempo, pero en algunos casos requerimos que nuestro archivo no sea compartido por ninguno de los subprocesos y no sea accesible.

Para tal requisito, NIO proporciona nuevamente una API conocida como FileLock que se utiliza para proporcionar bloqueo en todo el archivo o en una parte del archivo, de modo que ese archivo o su parte no se comparta o no sea accesible.

Para proporcionar o aplicar dicho bloqueo, tenemos que usar FileChannel o AsynchronousFileChannel, que proporciona dos métodos lock() y tryLock()para este propósito La cerradura provista puede ser de dos tipos:

  • Exclusive Lock - Un bloqueo exclusivo evita que otros programas adquieran un bloqueo superpuesto de cualquier tipo.

  • Shared Lock - Un bloqueo compartido evita que otros programas que se ejecutan simultáneamente adquieran un bloqueo exclusivo superpuesto, pero les permite adquirir bloqueos compartidos superpuestos.

Métodos utilizados para obtener un archivo de bloqueo -

  • lock() - Este método de FileChannel o AsynchronousFileChannel adquiere un bloqueo exclusivo sobre un archivo asociado con el canal dado. El tipo de retorno de este método es FileLock, que se utiliza además para monitorear el bloqueo obtenido.

  • lock(long position, long size, boolean shared) - Este método nuevamente es el método de bloqueo sobrecargado y se usa para bloquear una parte particular de un archivo.

  • tryLock() - Este método devuelve un FileLock o un nulo si el bloqueo no se pudo adquirir e intenta adquirir un bloqueo explícitamente exclusivo en el archivo de este canal.

  • tryLock(long position, long size, boolean shared) - Este método intenta adquirir un bloqueo en la región dada del archivo de este canal, que puede ser de tipo exclusivo o compartido.

Métodos de la clase FileLock

  • acquiredBy() - Este método devuelve el canal en cuyo archivo se adquirió el bloqueo.

  • position() - Este método devuelve la posición dentro del archivo del primer byte de la región bloqueada. Una región bloqueada no necesita estar contenida dentro, o incluso superponerse, al archivo subyacente real, por lo que el valor devuelto por este método puede exceder el tamaño actual del archivo.

  • size() - Este método devuelve el tamaño de la región bloqueada en bytes. No es necesario que una región bloqueada esté contenida dentro del archivo subyacente real, ni siquiera se superponga, por lo que el valor devuelto por este método puede exceder el tamaño actual del archivo.

  • isShared() - Este método se utiliza para determinar si el bloqueo se comparte o no.

  • overlaps(long position,long size) - Este método indica si este bloqueo se superpone o no al rango de bloqueo dado.

  • isValid() - Este método indica si el bloqueo obtenido es válido o no. Un objeto de bloqueo permanece válido hasta que se libera o se cierra el canal de archivos asociado, lo que ocurra primero.

  • release()- Libera el bloqueo obtenido. Si el objeto de bloqueo es válido, al invocar este método se libera el bloqueo y el objeto no es válido. Si este objeto de bloqueo no es válido, la invocación de este método no tiene ningún efecto.

  • close()- Este método invoca el método release (). Se agregó a la clase para que pueda usarse junto con la construcción del bloque de administración automática de recursos.

Ejemplo para demostrar el bloqueo de archivos.

El siguiente ejemplo crea un bloqueo sobre un archivo y escribe contenido en él

package com.java.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class FileLockExample {
   public static void main(String[] args) throws IOException {
      String input = "Demo text to be written in locked mode.";  
      System.out.println("Input string to the test file is: " + input);  
      ByteBuffer buf = ByteBuffer.wrap(input.getBytes());  
      String fp = "D:file.txt";  
      Path pt = Paths.get(fp);  
      FileChannel channel = FileChannel.open(pt, StandardOpenOption.WRITE,StandardOpenOption.APPEND);  
      channel.position(channel.size() - 1); // position of a cursor at the end of file       
      FileLock lock = channel.lock();   
      System.out.println("The Lock is shared: " + lock.isShared());  
      channel.write(buf);  
      channel.close(); // Releases the Lock  
      System.out.println("Content Writing is complete. Therefore close the channel and release the lock.");  
      PrintFileCreated.print(fp);  
   }  
}
package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class PrintFileCreated {
   public static void print(String path) throws IOException {  
      FileReader filereader = new FileReader(path);  
      BufferedReader bufferedreader = new BufferedReader(filereader);  
      String tr = bufferedreader.readLine();    
      System.out.println("The Content of testout.txt file is: ");  
      while (tr != null) {      
         System.out.println("    " + tr);  
         tr = bufferedreader.readLine();  
      }  
   filereader.close();  
   bufferedreader.close();  
   }  
}

Salida

Input string to the test file is: Demo text to be written in locked mode.
The Lock is shared: false
Content Writing is complete. Therefore close the channel and release the lock.
The Content of testout.txt file is: 
To be or not to be?Demo text to be written in locked mode.