文件锁(FileLock),使用文件锁锁住文件后,其他进程不能操作读或写文件,除非当前进程release或unlock文件锁。
前两天看码云上的oim项目源码,该项目即使用了文件锁来防止同一账户重复登录(当然,该方法是不太合理的,因为用户换一台电脑或修改锁文件路径即可同一账户重复登录,但也是一个文件锁使用的不错的例子)
文件锁分为共享锁、独占锁,加锁方式有阻塞(lock())和非阻塞(tryLock())。
tryLock或lock时使用参数如fileChannel.tryLock(0L, Long.MAX_VALUE, true),即可使用共享锁
以下实例代码为独占锁实例,先运行FileLockTest 再运行BlockLock
FileLockTest .java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package file.lock;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
*
* @author Administrator
*/
public class FileLockTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException,IOException{
File file;
FileChannel fileChannel;
RandomAccessFile randomAccessFile;
String path = "C:\\Users\\Administrator\\Desktop\\lock\\my.lock";
file = new File(path);
if(!file.exists()){
file.createNewFile();
}
randomAccessFile = new RandomAccessFile(file, "rw");
//通过RandomAccessFile获取FileChannel
fileChannel = randomAccessFile.getChannel();
/*****
* tryLock非阻塞,抢不到锁立即返回null
* lock阻塞锁,抢不到锁一直等待
*/
//通过FileChannel进行tryLock()
final FileLock fileLock = fileChannel.tryLock();
if(null == fileLock){
System.out.println("老大,属下无能,文件已经被其他进程锁住!");
}else{
if(fileLock.isValid()){
System.out.println("老大,本进程已经先行一步锁住了文件了!");
new Thread(
new Runnable() {
@Override
public void run() {
try {
//当前文件应该处于被锁住状态,20后解锁,阻塞锁lock会立即获取锁
Thread.sleep(20 * 1000);
randomAccessFile.read();
System.out.println("我读完了,我要释放锁!");
fileLock.release();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
).start();
}
}
exit();
}
private static void exit(){
while (true) {
try {
Thread.sleep(10 * 10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
BlockLock.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package file.lock;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
*
* @author Administrator
*/
public class BlockLock {
public static void main(String[] args) throws FileNotFoundException, IOException {
File file;
FileChannel fileChannel;
RandomAccessFile randomAccessFile;
String path = "C:\\Users\\Administrator\\Desktop\\lock\\my.lock";
file = new File(path);
if(!file.exists()){
file.createNewFile();
}
randomAccessFile = new RandomAccessFile(file, "rw");
//通过RandomAccessFile获取FileChannel
fileChannel = randomAccessFile.getChannel();
FileLock tempLock = fileChannel.tryLock();
if(null == tempLock){
System.out.println("我拿不到文件锁,交给阻塞锁lock()拿吧!");
System.out.println("开始测试阻塞锁...");
FileLock fileLock2 = fileChannel.lock();
if(null == fileLock2){
}else{
if(fileLock2.isValid()){
System.out.println("老大,那小子一释放锁,就被我抢到了!厉害不!");
}
}
}else{
System.out.println("使用非阻塞锁拿到了文件锁...");
}
}
}
运行结果如下:
FileLockTest:
老大,本进程已经先行一步锁住了文件了!
我读完了,我要释放锁!
BlockLock:
我拿不到文件锁,交给阻塞锁lock()拿吧!
开始测试阻塞锁...
老大,那小子一释放锁,就被我抢到了!厉害不!
如有错误,欢迎指正
end