Java处理多人同时读写文件的文件锁处理

原文转载自http://blog.csdn.net/gxy3509394/article/details/7435993

最近项目中有遇到并发同时访问一个文件读写的情况、但是同时读写就会出错、所以我研究了一下java文件锁这个机制下面直接贴代码

我通过的是线程来模拟多人同时读写的情况

写文件

package com.dnion.test;

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;
/**
 * @author chb
 */
public class Thread_writeFile extends Thread{
    public void run(){
        Calendar calstart=Calendar.getInstance();
        File file=new File("D:/test.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) {
                     System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒");
                     sleep(1000);
                }

            }

            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) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Calendar calend=Calendar.getInstance();
        System.out.println("写文件共花了"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"秒");
    }
}

  读文件

package com.dnion.test;

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;
import java.util.Calendar;
/**
 * @author chb
 */
public class Thread_readFile extends Thread{
    public void run(){
        try {
            Calendar calstart=Calendar.getInstance();
            sleep(5000);
            File file=new File("D:/test.txt");      

            //给该文件加锁
            RandomAccessFile fis = new RandomAccessFile(file, "rw");
            FileChannel fcin=fis.getChannel();
            FileLock flin=null;
            while(true){
                try {
                    flin = fcin.tryLock();
                    break;
                } catch (Exception 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 (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  

调用

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

我们通过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时 为共享锁

时间: 2024-10-12 23:30:16

Java处理多人同时读写文件的文件锁处理的相关文章

java对比IO和NIO的文件读写性能测试

原文:java对比IO和NIO的文件读写性能测试 源代码下载地址:http://www.zuidaima.com/share/1550463508466688.htm 1. NIO采用更接近操作系统执行IO的方式:通道和缓存器:顾名思义,数据源的数据由缓存器通过通道进行传输. 2. 在JDK5之后,原始IO系统底层用NIO进行了优化,这可以通过sun公布的源码中找到,但是,NIO系统性还是比IO强. 3. 在稍微研究了IO源码以及部分sun源码,我觉得IO系统的性能瓶颈主要是由于原始的IO架构因

java读写文件

读文件 package tool; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; public class ReadFile { pu

java读写文件,读超大文件

一直在处理爬虫,经常能遇到读写文件的操作,很多时候都是读写超大文件,记录如下: 一.读文件 import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException;

java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果文件超大的话,更快的方式是采用MappedByteBuffer. MappedByteBuffer是java nio引入的文件内存映射方案,读写性能极高.NIO最主要的就是实现了对异步操作的支持.其中一种通过把一个套接字通道(SocketChannel)注册到一个选择器(Selector)中,不时调用后者的选择(select)方法就能返回满足的选择键(SelectionKey

Java读写文件方法总结

Java的读写文件方法在工作中相信有很多的用处的,本人在之前包括现在都在使用Java的读写文件方法来处理数据方面的输入输出,确实很方便.奈何我的记性实在是叫人着急,很多时候既然都会想不起来怎么写了,不过我的Java代码量也实在是少的可怜,所以应该多多练习.这里做一个总结,集中在一起方面今后查看. Java读文件 1 package 天才白痴梦; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.F

Java读写文件的几种方式

自工作以后好久没有整理Java的基础知识了.趁有时间,整理一下Java文件操作的几种方式.无论哪种编程语言,文件读写操作时避免不了的一件事情,Java也不例外.Java读写文件一般是通过字节.字符和行三种方式来进行文件的操作. import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.F

java byte【】数组与文件读写(增加新功能)

今天在测试直接写的文章: java byte[]数组与文件读写 时,想调用FileHelper类对字节数组以追加的方式写文件,结果无论怎样竟然数据录入不全,重新看了下文件的追加模式,提供了两种方式: 方式一: 字节数组写入文件(不追加) //将byte数组写入文件 public void createFile(String path, byte[] content) throws IOException { FileOutputStream fos = new FileOutputStream(

SAE java应用读写文件(TmpFS和Storage)-----绝世好代码

近期不少java用户都在提sae读写本地文件的问题,在这里结合TmpFS和Storage服务说说java应用应该如何读写文件TmpFS是一个供应用临时读写的路径,但请求过后将被销毁.出于安全考虑,sae限制了应用对本地IO操作,但本地操作肯定是存在的,所以sae提供了TmpFS来应对.如果需要将文件持久化怎么办呢?当然是使用storage.下面给出一个例子结合storage和TmpFS来写文件首先使用common-upload将文件上传至TmpFS下,之后再使用SaeStorage对象将文件存储

java.io几种读写文件的方式

一.Java把这些不同来源和目标的数据都统一抽象为数据流. Java语言的输入输出功能是十分强大而灵活的. 在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流. 这里介绍几种读写文件的方式 二.InputStream.OutputStream(字节流) //读取文件(字节流) InputStream in = new FileInputStream("d:\\1.txt"); //写入相应的文件