Java文件锁的用法(附带实例)
从 JDK 1.4 的 NIO 开始,Java 提供了文件锁的支持。
文件锁在操作系统中很常见,当多个运行的程序需要并发修改同一个文件时,程序之间需要使用某种机制来进行通信。使用文件锁可以有效阻止多个程序或进程同时修改同一个文件,以免造成读/写文件的混乱。
使用文件锁可以控制文件的全部或部分字节的访问。在 NIO 中,Java 提供的 FileLock 类支持文件锁定功能。FileChannel 类提供的 lock() 方法和 tryLock() 方法用来获得文件锁 FileLock 对象,从而锁定文件。有两种文件的锁定方式:排他锁和共享锁。FileLock 类在 java.nio 包中,FileChannel 类在 java.nio.channels 包中。
下面结合 RandomAccessFile 类来说明文件锁的使用方法。
RandomAccessFile 类创建的流在读/写文件时可以使用文件锁,只要不解除该锁,其他程序就无法操作被锁定的文件。使用文件锁的步骤如下:
1) 使用 RandomAccessFile 类创建指向文件的流对象,该对象的读/写属性必须是 rw,即可读可写。例如:
2) input 流调用 getChannel() 方法获得一个连接底层文件的 FileChannel 对象(信道)。例如:
3) 信道调用 tryLock() 方法或 lock() 方法获得一个 FileLock 对象,这个过程也被称为对文件加锁。例如:
lock() 方法和 tryLock() 方法的区别包括以下几点:
如果只是想锁定文件的部分内容而不是锁定全部内容,那么可以使用如下方法:
说明:当参数 shared 为 true 时,表示该锁是一个共享锁,允许多个进程来读取该文件,但是阻止其他进程获得对该文件的排他锁。当参数 shared 为 false 时,表示该锁是一个排他锁,将锁住对该文件的读/写。程序可以通过调用 FileLock 的 isShared 来判断获得的锁是否为共享锁。
4) 处理完文件之后通过 FileLock 对象的 release() 方法释放文件锁。例如:
【实例】先对指定的文件执行加锁操作,并且程序暂停 1 秒,再释放文件锁。
文件锁在操作系统中很常见,当多个运行的程序需要并发修改同一个文件时,程序之间需要使用某种机制来进行通信。使用文件锁可以有效阻止多个程序或进程同时修改同一个文件,以免造成读/写文件的混乱。
使用文件锁可以控制文件的全部或部分字节的访问。在 NIO 中,Java 提供的 FileLock 类支持文件锁定功能。FileChannel 类提供的 lock() 方法和 tryLock() 方法用来获得文件锁 FileLock 对象,从而锁定文件。有两种文件的锁定方式:排他锁和共享锁。FileLock 类在 java.nio 包中,FileChannel 类在 java.nio.channels 包中。
下面结合 RandomAccessFile 类来说明文件锁的使用方法。
RandomAccessFile 类创建的流在读/写文件时可以使用文件锁,只要不解除该锁,其他程序就无法操作被锁定的文件。使用文件锁的步骤如下:
1) 使用 RandomAccessFile 类创建指向文件的流对象,该对象的读/写属性必须是 rw,即可读可写。例如:
RandomAccessFile input = new RandomAccessFile("Example.java", "rw");
2) input 流调用 getChannel() 方法获得一个连接底层文件的 FileChannel 对象(信道)。例如:
FileChannel fileChannel = input.getChannel();
3) 信道调用 tryLock() 方法或 lock() 方法获得一个 FileLock 对象,这个过程也被称为对文件加锁。例如:
FileLock lock = fileChannel.tryLock();
lock() 方法和 tryLock() 方法的区别包括以下几点:
- 当使用 lock() 方法尝试锁定某个文件时,如果获得了文件锁,那么该方法会返回该文件锁,否则返回 null;
- 当使用 tryLock() 方法尝试锁定文件时,将直接返回而不是阻塞。如果获得了文件锁,那么该方法会返回文件锁,否则返回 null。
如果只是想锁定文件的部分内容而不是锁定全部内容,那么可以使用如下方法:
- lock(long position, long size, boolean shared):对文件从 position 开始且长度为 size 的内容加锁,该方法是阻塞式的;
- tryLock(long position, long size, boolean shared):对文件从 position 开始且长度为 size 的内容加锁,该方法是非阻塞式的。
说明:当参数 shared 为 true 时,表示该锁是一个共享锁,允许多个进程来读取该文件,但是阻止其他进程获得对该文件的排他锁。当参数 shared 为 false 时,表示该锁是一个排他锁,将锁住对该文件的读/写。程序可以通过调用 FileLock 的 isShared 来判断获得的锁是否为共享锁。
4) 处理完文件之后通过 FileLock 对象的 release() 方法释放文件锁。例如:
lock.release();
【实例】先对指定的文件执行加锁操作,并且程序暂停 1 秒,再释放文件锁。
import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class Example { public static void main(String[] args) { try { // 创建指向某文件的输入/输出流对象 RandomAccessFile input = new RandomAccessFile("D:\\chapter\\a.txt", "rw"); // 获得连接底层文件的信道 FileChannel fileChannel = input.getChannel(); // 获得 FileLock 对象,对文件加锁 FileLock lock = fileChannel.tryLock(); // 程序在此处暂停 1 秒 Thread.sleep(1000); // 释放文件锁 lock.release(); } catch (Exception e) { e.printStackTrace(); } } }实例的运行结果不可见,请读者自行验证。