java实现多个线程互斥访问文件

首先介绍一下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();
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值