package com.judy.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* FileChannel的tryLock()方法获取文件锁,此外也可以使用lock()方法,该方法与tryLock()方法的区别在于lock()
* 是一个阻塞性方法,只有获取文件锁才能进行后续操作,否则一直等待
*
* @author judy
*/
public class FileLockT {
public static void main(String[] args) throws Exception {
FileReadT1 r1 = new FileReadT1();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
t1.start();
t2.start();
}
}
class FileReadT1 implements Runnable {
private static Log log1 = LogFactory.getLog(FileLockT.class);
@Override
public void run() {
// 不可使用FileInputStream可以获取getChannel()方法,但是获取的对象不能实现文件的锁定
// FileInputStream fis = new FileInputStream("d:\\xmlwrite.txt");
try (RandomAccessFile fis = new RandomAccessFile(new File("d:\\xmlwrite.txt"), "rw");
FileChannel fc = fis.getChannel()) {
// 尝试获取文件锁,如果有其他用户在使用并返回null
// FileLock fl = fc.tryLock();
FileLock fl = fc.lock();
// tryLock与lock实现依赖底层平台的支持
// 对独占锁和共享锁的支持必须由底层的操作系统提供。锁的类型可以通过FileLock.isShared()进行查询。另外,我们不能获取缓冲器上的锁,只能是通道上的。
boolean shared = fl.isShared();
System.out.println("锁的类型为..." + shared);
if (fl.isValid()) {
log1.info(Thread.currentThread().getName()+" 11111允许执行读写操作!");
System.out.println(Thread.currentThread().getName()+" 11111允许执行读写操作!");
// Thread.sleep(2000);
fl.release();
} else {
log1.info("11111其他用户在执行读写操作!");
System.out.println("11111其他用户在执行读写操作!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行结果:Thread-0 11111允许执行读写操作!
并抛异常:java.nio.channels.OverlappingFileLockException
注释:来自http://blog.youkuaiyun.com/gxy3509394/article/details/7435993
OverlappingFileLockException 与锁的作用域
在某个文件加锁锁只会作用在此文件上对其他文件无效
单个 Java 虚拟机在某个特定文件上所保持的锁定是不重叠的,即同一个jvm中不同线程去拿同一文件的锁时,先拿到的获得锁,后获取的无法获得锁,tryLock()方法不会抛出异常,但获得锁值为null。
不同jvm或者不同操作系统获取同一文件锁时,先拿到的获得锁,后获取的抛出文件重叠锁异常【OverlappingFileLockException】。以上是windows才会出现如此现象,如果是Linux 会抛出异常:【java.io.IOException:Permission denied】
共享锁与独占锁区别
独占锁:也称排它锁,如果一个线程获得一个文件的独占锁,那么其它线程就不能再获得同一文件的独占锁或共享锁,直到独占锁被释放。
共享锁:如果一个线程获得一个文件的共享锁,那么其它线程可以获得同一文件的共享锁或同一文件部分内容的共享锁,但不能获取排它锁
当a.txt文件被加独占锁时 其他线程不可读也不可写
当a.txt文件被加共享锁时 其他线程可读也不可写
如何获得共享锁
fc.tryLock(position,size,isShare);第三个参数为true时 为共享锁