Java Nio 简明教程

Java NIO - FileLock

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

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

为了提供或应用此类锁,我们必须使用 FileChannel 或 AsynchronousFileChannel,它们为此目的提供了两个方法,分别是 lock()tryLock()。提供的锁可以是两种类型之一:

  1. Exclusive Lock - 独占锁阻止其他程序获取任何类型的重叠锁。

  2. Shared Lock - 共享锁阻止其他并发运行的程序获取重叠的独占锁,但允许它们获取重叠的共享锁。

用于获取文件锁的方法:

  1. lock() − FileChannel 或 AsynchronousFileChannel 的这种方法获取与给定通道相关联的文件的独占锁。此方法的返回类型是 FileLock,用于进一步监控获取的锁。

  2. lock(long position, long size, boolean shared) − 此方法再次是 lock 方法的重载方法,用于锁定文件的特定部分。

  3. tryLock() − 此方法返回 FileLock 或 null(如果获取不到锁),它尝试获取此通道文件的显式独占锁。

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

Methods of FileLock Class

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

  2. position() − 此方法返回已锁定区域的第一个字节在文件中的位置。已锁定的区域不必包含在实际基础文件中,甚至不必与之重叠,因此此方法返回的值可能超出文件的当前大小。

  3. size() − 此方法以字节为单位返回已锁定区域的大小。已锁定的区域不必包含在实际基础文件中,甚至不必与之重叠,因此此方法返回的值可能超出文件的当前大小。

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

  5. overlaps(long position,long size) − 此方法说明此锁是否与给定的锁范围重叠。

  6. isValid() − 此方法说明获取的锁是否有效。在释放锁或关闭关联文件通道(以先发生者为准)之前,锁对象将保持有效状态。

  7. release() − 释放获取的锁。如果锁对象有效,调用此方法将释放锁并将对象渲染为无效。如果此锁对象无效,则调用此方法不会产生任何效果。

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

Example to demonstrate file lock.

下面的示例创建文件锁并在其中写入内容

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

Output

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.