Java NIO - FileLock

众所周知,Java NIO 支持并发和多线程,这使得它能够处理同时对多个文件进行操作的多个线程。但在某些情况下,我们要求我们的文件不会被任何线程共享,并且无法访问。

对于这种要求,NIO 再次提供了一个称为 FileLock 的 API,用于对整个文件或文件的一部分进行锁定,以便文件或其部分不会被共享或访问。

为了提供或应用这种锁,我们必须使用 FileChannel 或 AsynchronousFileChannel,它们为此目的提供了两种方法 lock()tryLock()。提供的锁可能有两种类型 −

  • 排他锁 −独占锁可防止其他程序获取任一类型的重叠锁。

  • 共享锁 − 共享锁可防止其他同时运行的程序获取重叠的独占锁,但允许它们获取重叠的共享锁。

用于获取文件锁的方法 −

  • lock() − FileChannel 或 AsynchronousFileChannel 的此方法获取与给定通道关联的文件的独占锁。此方法的返回类型为 FileLock,它进一步用于监视获取的锁。

  • lock(long position, long size, boolean shared) −此方法同样是 lock 方法的重载方法,用于锁定文件的特定部分。

  • tryLock() − 如果无法获取锁定,则此方法返回 FileLock 或 null,并尝试获取此通道文件的显式独占锁定。

  • tryLock(long position, long size, boolean shared) − 此方法尝试获取此通道文件给定区域的锁定,该锁定可能是独占或共享类型。

FileLock 类的方法

  • acquiredBy() − 此方法返回获取文件锁定的通道。

  • position() −此方法返回锁定区域第一个字节在文件中的位置。锁定区域不需要包含在实际底层文件中,甚至不需要与实际底层文件重叠,因此此方法返回的值可能超过文件的当前大小。

  • size() − 此方法以字节为单位返回锁定区域的大小。锁定区域不需要包含在实际底层文件中,甚至不需要与实际底层文件重叠,因此此方法返回的值可能超过文件的当前大小。

  • isShared() − 此方法用于确定锁是否共享。

  • overlaps(long position,long size) − 此方法告知此锁是否与给定的锁定范围重叠。

  • isValid() −此方法可判断所获取的锁是否有效。锁对象保持有效,直到被释放或关联的文件通道被关闭(以先发生者为准)。

  • release() − 释放所获取的锁。如果锁对象有效,则调用此方法将释放锁并使对象无效。如果此锁对象无效,则调用此方法无效。

  • close() − 此方法调用 release() 方法。它被添加到类中,以便可以与自动资源管理块构造结合使用。

演示文件锁的示例。

以下示例在文件上创建锁并将内容写入其中

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); // 光标在文件末尾的位置
    FileLock lock = channel.lock();
    System.out.println("The Lock is shared:" + lock.isShared());
    channel.write(buf);
    channel.close(); // 释放锁
    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();  
   }  
}

输出

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.