• 多线程并发思考文件加锁


    多线程并发思考--文件加锁

             在最近的工作中,经常要用到线程,就对线程相关知识稍微看了看,知道并发线程经常引起共享资源冲突,java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持.

             可是在工作中,我却碰到了这样的需求,定时抛出线程读写某文件的内容,由于相隔时间很短,我突然想到,会不会在第二次轮循开始对该文件进行读操作的时候,第一次抛出的线程还在对该文件进行写操作,如果有可能,那么第二次读出的数据会是什么样的呢?

            怀着这样的疑问,我开始以程序作实验,代码如下:

    1.用于写文件的线程

    package chb.thread;

    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Calendar;

    /**
     * 
    @author 崔红保
     *  
     *  这个线程用于写文件
     
    */

    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();
                FileWriter fw
    =new FileWriter(file);
                BufferedWriter bw
    =new BufferedWriter(fw);
                
    for(int i=0;i<1000;i++){
                    sleep(
    10);
                    bw.write(
    "这是第"+(i+1)+"行,应该没错哈 ");
                }

                bw.close();
                bw
    =null;
                fw.close();
                fw
    =null;
            }
     catch (IOException e) {
                e.printStackTrace();
            }
     catch (InterruptedException e) {
                e.printStackTrace();
            }

            Calendar calend
    =Calendar.getInstance();
            System.out.println(
    "写文件共用了"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"毫秒");
        }


    }

    2.用于读文件的线程

    package chb.thread;

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.Calendar;

    /**
     * 
    @author 崔红保
     *
     *这个线程用于读文件
     
    */

    public class Thread_readFile extends Thread{
        
    public void run(){
            
    try {
                Calendar calstart
    =Calendar.getInstance();
                sleep(
    5000);
                File file
    =new File("D:/test.txt");    
                BufferedReader br
    =new BufferedReader(new FileReader(file));
                String temp
    =null;
                temp
    =br.readLine();
                
    while(temp!=null){
                    System.out.println(temp);
                    temp
    =br.readLine();
                }

                
                br.close();
                br
    =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();
            }

        }

    }

    3.分别启用两个线程

            Thread_writeFile thf3=new Thread_writeFile();
            Thread_readFile thf4
    =new Thread_readFile();
            thf3.start();
            thf4.start();

    4.结果分析

    虽然写文件的操作开始5秒钟后,读文件的操作才开始进行,可是读文件的线程并没有读出数据,改变时间,读出的数据也就各不相同.

             为了避免以上结果,我们希望在一个线程在操作某个文件的时候,其他线程不能对该文件进行读或写操作,要怎么才能实现呢?利用java提供的synchronized似乎无法完成,因为每个线程是在程序中动态抛出的.郁昧了一天之后,我终于找到了一个解决办法,就是利用java.nio包中的FileChannel对文件进行加锁.

             具体实现方法如下:

    1.写文件的线程

    package chb.thread;

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    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();
                            
                
    //对该文件加锁
                FileOutputStream out=new FileOutputStream(file,true);
                FileChannel fcout
    =out.getChannel();
                FileLock flout
    =null;
                
    while(true){
                    flout
    =fcout.tryLock();
                    
    if(flout!=null){
                        
    break;
                    }

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

                }

            
                
    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())+"");
        }

    }

    2.读文件的线程

    package chb.thread;

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    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");    
                
                
    //给该文件加锁
                FileInputStream fis=new FileInputStream(file);
                FileChannel fcin
    =fis.getChannel();
                FileLock flin
    =null;
                
    while(true){
                    flin
    =fcin.tryLock(0,Long.MAX_VALUE,true);
                    
    if(flin!=null){
                        
    break;
                    }

                    
    else{
                        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();
            }

        }

    }

    3.分别启用两个线程

            Thread_writeFile thf3=new Thread_writeFile();
            Thread_readFile thf4
    =new Thread_readFile();
            thf3.start();
            thf4.start();

    4.结果分析

    以上程序在对一个文件执行写操作前,先对该文件加锁,这样其他线程就不能再对该文件操作,等该线程的写操作结束,释放资源,其他线程才可以继续对该文件执行相应的读写操作.

    可是,郁昧的是,这段程序在windows下可以正确执行,在linux下却无效.根据<Thinking in Java>上的观点是:对独占锁或者共享锁的支持必须由底层的操作系统提供.

              综观我的解决方法,总感觉不太完美,各位如有好的方法来判断一个文件是否正被某个线程使用,希望大家一起分享一下.

  • 相关阅读:
    翻译一下libtiff的手册
    LIBTIFF读写黑白TIFF
    LIBTIFF存储代码,存图、拼图
    几点TIFF的说明
    TIFF Tag TileWidth
    TIFF Tag Orientation
    OpenCV 加速图像处理
    Qt QString 、String、char* 三者之间相互转换
    PackBits解压缩算法
    关于LZW算法的压缩与解压缩
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330262.html
Copyright © 2020-2023  润新知