java 读文件 加锁吗_Java处理多人同时读写文件的文件锁处理

线程写:

package nio.lock;

import java.io.File;

import java.io.IOException;

import java.io.RandomAccessFile;

import java.nio.channels.FileChannel;

import java.nio.channels.FileLock;

import java.util.Calendar;

public class Thread_writeFile extends Thread {

@Override

public void run() {

Calendar calstart = Calendar.getInstance();

File file = new File("D:\\1701.txt");

try {

if (!file.exists()) {

file.createNewFile();

}

//对文件进行加锁

RandomAccessFile out=new RandomAccessFile(file,"rw");

FileChannel fcout=out.getChannel();

FileLock flout=null;

while(true){

try {

flout=fcout.tryLock();

break;

} catch (Exception e) {

// TODO Auto-generated catch block

System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒!");

try {

sleep(1000);

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

}

for(int i=1;i<1000;i++){

sleep(10);

StringBuffer sb=new StringBuffer();

sb.append("这是第"+i+"行");

out.write(sb.toString().getBytes("utf-8"));

}

flout.release();

fcout.close();

out.close();

out=null;

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Calendar calend=Calendar.getInstance();

System.out.println("写文件共花了:"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"毫秒");

}

}

线程读:

package nio.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;

import java.util.Calendar;

public class Thread_readFile extends Thread {

@Override

public void run() {

Calendar calstart = Calendar.getInstance();

try {

// sleep(25000);

sleep(5000); //同时读写

File file = new File("D:\\1701.txt");

// 给该文件加锁

RandomAccessFile fis = new RandomAccessFile(file, "rw");

FileChannel fcin = fis.getChannel();

FileLock flin = null;

while (true) {

try {

flin = fcin.tryLock();

break;

} catch (IOException e) {

System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒");

sleep(1000);

}

}

byte[] buf=new byte[1024];

StringBuffer sb=new StringBuffer();

while((fis.read(buf))!=-1){

sb.append(new String(buf,"utf-8"));

buf=new byte[1024];

}

System.out.println(sb.toString());

flin.release();

fcin.close();

fis.close();

fis=null;

Calendar

calend=Calendar.getInstance();

System.out.println("读文件共花了"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"秒");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

测试:

package nio.lock;

public class Test {

public static void main(String[] args) {

Thread_writeFile wr=new Thread_writeFile();

Thread_readFile rf=new Thread_readFile();

wr.start();

rf.start();

}

}

这里我们要讲解一下文件锁

我们通过RandomAccessFile这个随机读取流来操作文件速度上会有一点慢,但不是极其大的文件一般可以忽略。我们通过FileChannel对象来获得锁

Trylock与lock方法

trylock()是非阻塞式的,它设法获取锁,但如果不能获得,例如因为其他一些进程已经持有相同的锁,而且不共享时,它将直接从方法调用返回。

lock()是阻塞式的,它要阻塞进程直到锁可以获得,或调用lock()的线程中继,或调用lock()的通道关闭

对独占锁和共享锁的支持必须由底层的操作系统提供。锁的类型可以通过FileLock.isShared()进行查询,我们不能获取缓冲器上的锁,只能是通道上的。

OverlappingFileLockException与锁的作用域

在某个文件加锁锁只会作用在此文件上对其他文件无效

单个Java虚拟机在某个特定文件上所保持的锁定是不重叠的,即同一个jvm中不同线程去拿同一文件的锁时,先拿到的获得锁,后获取的无法获得锁,tryLock()方法不会抛出异常,但获得的锁值为null。

不同jvm或者不同操作系统获取同一文件锁时,先拿到的获得锁,后获取的抛出文件重叠锁异常【OverlappingFileLockException】。以上是windows才会出现如此现象,如果是linux会抛出异常:【java.io.IOException:Permission

denied】

共享锁和独占锁区别

独占锁:也称排它锁,如果一个线程获得一个文件的独占锁,那么其它线程就不能再获得同一文件的独占锁或共享锁,直到独占锁被释放。

共享锁:如果一个线程获得一个文件的共享锁,那么其它线程可以获得同一文件的共享锁或同一文件部分内容的共享锁,但不能获取排它锁

当a.txt文件被加独占锁时

其它线程不可读也不可写

当a.txt文件被加共享锁时

其它线程可读但不可写

如何获得共享锁

fc.tryLock(position,size,isShare);第三个参数为true时,为共享锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值