首先介绍一下JAVA的文件锁
java文件锁:
文件锁类似于Java中的对象锁,可以锁定整个文件或文件的一部分,又分为独占锁、共享锁。
独占锁:也称排它锁,如果一个线程获得一个文件的独占锁,那么其它线程就不能再获得同一文件的独占锁或共享锁,直到独占锁被释放。
共享锁:如果一个线程获得一个文件的共享锁,那么其它线程可以获得同一文件的共享锁或同一文件部分内容的共享锁,但不能获取排它锁。
两个线程利用共享文件传递信息时,需要给文件加锁,实现文件的互斥访问。可以通过FileChannel和FileLock类实现文件的加锁操作。
注意事项:
1、出现的错误:
java.nio.channels.NonWritableChannelException
解释原因和解决办法:
FileLock不能对只读Channel上锁。即由FileInPutStream获得的channel
将 FileInputStream fis = new FileInputStream(file);
改为RandomAccessFile raf = new RandomAccessFile(file, "rw");
从RandomAccessFile获得通道就可以了。
当写线程对文件加锁后,可以对文件利用FileOutPutStream进行写入操作;但是在另一个线程读文件时,不能利用FileInPutStream进行读操作,此时需要利用RandomAccessFile 类获取对文件的随机读写权限即RandomAccessFile fis=new RandomAccessFile(file, "rw");
2、释放锁的时候需要先释放filelock锁再释放filechannel
写文件的操作:
FileOutputStream fos = new FileOutputStream(file);
FileChannel wfilechannel = fos.getChannel();
FileLock wfilelock = null;while (true) {
// 独占锁
wfilelock = wfilechannel.tryLock(0, 2, false);//false代表独占所,即在同一时间只有一个线程可以使用该文件进行读写操作;共享锁可以有多个线程读该文件,但是只有一个线程可以写该文件。
if (wfilelock != null) {
// 获得文件操作
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(usercontral);
// 释放锁,通道
wfilelock.release();
wfilechannel.close();
// 关闭写流
oos.close();
System.out.println("释放锁,关闭流!!");
break;
} else {
System.out.println("写文件时,文件被其他进程占用!!");
}
读文件的操作:
try {
//随机存取文件
RandomAccessFile fis=new RandomAccessFile(file, "rw");
fis.read(bytes);
//文件加锁,FileChannel
FileChannel rfilechannel=fis.getChannel();
FileLock rfilelock=rfilechannel.tryLock(0,2,false);
if(rfilelock!=null){
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
//获得文件操作
ObjectInputStream ois=new ObjectInputStream(bais);
usercontral=(UserContralMesg)ois.readObject();
//释放锁,通道
rfilelock.release();
rfilechannel.close();
fis.close();
//关闭读流
ois.close();
System.out.println("删除saveUserContralMsg文件");
//提取完任务删除文件
file.delete();
}
else{
System.out.println("读文件时,有其它线程在操作该文件!!休眠1000毫秒!!");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(OverlappingFileLockException e){
System.out.println("OverlappingFileLockException:休眠1000毫秒!!");
e.printStackTrace();
}
catch(NonWritableChannelException e){
e.printStackTrace();
}
}
//等待1000毫秒,,让写线程获得运行机会
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}