β

[NIO.2] 锁定文件

Aptusource.orgAptusource.org 319 阅读

File 锁定机制是限制用户访问文件或其它数据,用于确保不会发生两个或多个用户同时修改相同文件的情况。这种保护方式是典型的文件更新解决方案。通常,当第一个用户访问文件的时候,文件被锁定(只能读,不能写),直到用户完成文件操作。

精确的文件锁定策略是平台相关的,在有些平台上,文件锁是建议性的(如果应用没有检查文件锁,那么任何应用都可以访问文件),在有的平台上,文件锁是强制性的(文件锁将保护文件不被应用程序访问)。

我们可以通过 NIO API 在 Java 应用程序中使用文件锁。但是,无法保证文件锁能够精确地遵循你的设计。这取决于底层操作系统是否支持,有时候,错误的实现将会影响的预期。因此,请记住以下几点:

FileChannel 类提供了四个方法用于文件锁定:两个 lock 方法和两个 tryLock() 方法。 lock() 方法将会阻塞程序,直到返回文件锁。而 tryLock() 方法不会阻塞程序,当无法获取文件锁的时候将会返回 null 或抛出异常。两个 lock 和 tryLock() 方法中,有一个用于返回整个文件的文件锁,另一个用于返回文件区域的文件锁(这个方法需要设置是否允许共享文件锁)。

为了演示文件锁,我们使用两个应用程序。第一个将锁定 C:\rafaelnadal\email\vamos.txt 文件 2 分钟,直到写入一些文本内容。第二个将试图在这 2 分钟时间中向文件添加内容。如果文件成功被锁 2 分钟,那么第二个应用程序将会抛出 IOException,并且输出类似下面的消息:

The process cannot access the file because another process has locked a portion of the file.

下面是第一个应用:

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; 
import java.util.EnumSet; 
 
public class Main { 
 
 public static void main(String[] args) { 
 
   Path path = Paths.get("C:/rafaelnadal/email", "vamos.txt"); 
   ByteBuffer buffer = ByteBuffer.wrap("Vamos Rafa!".getBytes()); 
 
   try (FileChannel fileChannel = (FileChannel.open(path, EnumSet.of(StandardOpenOption.READ,  
                                                                StandardOpenOption.WRITE)))) { 
 
    // Use the file channel to create a lock on the file. 
    // This method blocks until it can retrieve the lock. 
    FileLock lock = fileChannel.lock(); 
 
     // Try acquiring the lock without blocking. This method returns 
     // null or throws an exception if the file is already locked. 
     //try { 
        //    lock = fileChannel.tryLock(); 
     //} catch (OverlappingFileLockException e) { 
         // File is already locked in this thread or virtual machine 
     //} 
 
     if (lock.isValid()) { 
 
         System.out.println("Writing to a locked file ..."); 
         try { 
             Thread.sleep(60000); 
             } catch (InterruptedException ex) { 
               System.err.println(ex); 
             } 
         fileChannel.position(0); 
         fileChannel.write(buffer); 
         try { 
             Thread.sleep(60000); 
         } catch (InterruptedException ex) { 
           System.err.println(ex); 
         } 
      } 
 
      // Release the lock 
      lock.release(); 
 
      System.out.println("\nLock released!"); 
 
     } catch (IOException ex) { 
       System.err.println(ex); 
     } 
  } 
}

运行上面的代码,并且在最多 2 分钟时间内并行运行下面的代码:

import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.nio.file.StandardOpenOption; 
import java.util.EnumSet; 
 
public class Main { 
 
 public static void main(String[] args) { 
 
   Path path = Paths.get("C:/rafaelnadal/email", "vamos.txt"); 
   ByteBuffer buffer = ByteBuffer.wrap("Hai Hanescu !".getBytes()); 
 
   try (FileChannel fileChannel = (FileChannel.open(path, EnumSet.of(StandardOpenOption.READ,  
                                                                StandardOpenOption.WRITE)))) { 
     fileChannel.position(0); 
     fileChannel.write(buffer); 
 
   } catch (IOException ex) { 
     System.err.println(ex); 
   } 
 } 
}

你会发现,第二个程序在 2 分钟之后,也就是第一个程序释放了锁之后,可以正常修改文件。

作者:Aptusource.orgAptusource.org
最好的 Java 技术博客
原文地址:[NIO.2] 锁定文件, 感谢原作者分享。

发表评论