日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

多線程并發(fā)思考--文件加鎖

 昵稱(chēng)2807 2007-09-26

多線程并發(fā)思考--文件加鎖

         在最近的工作中,經(jīng)常要用到線程,就對(duì)線程相關(guān)知識(shí)稍微看了看,知道并發(fā)線程經(jīng)常引起共享資源沖突,java以提供關(guān)鍵字synchronized的形式,為防止資源沖突提供了內(nèi)置支持.

         可是在工作中,我卻碰到了這樣的需求,定時(shí)拋出線程讀寫(xiě)某文件的內(nèi)容,由于相隔時(shí)間很短,我突然想到,會(huì)不會(huì)在第二次輪循開(kāi)始對(duì)該文件進(jìn)行讀操作的時(shí)候,第一次拋出的線程還在對(duì)該文件進(jìn)行寫(xiě)操作,如果有可能,那么第二次讀出的數(shù)據(jù)會(huì)是什么樣的呢?

        懷著這樣的疑問(wèn),我開(kāi)始以程序作實(shí)驗(yàn),代碼如下:

1.用于寫(xiě)文件的線程

package chb.thread;

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

/**
 * 
@author 崔紅保
 *  
 *  這個(gè)線程用于寫(xiě)文件
 
*/

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)+"行,應(yīng)該沒(méi)錯(cuò)哈 ");
            }

            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(
"寫(xiě)文件共用了"+(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 崔紅保
 *
 *這個(gè)線程用于讀文件
 
*/

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.分別啟用兩個(gè)線程

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

4.結(jié)果分析

雖然寫(xiě)文件的操作開(kāi)始5秒鐘后,讀文件的操作才開(kāi)始進(jìn)行,可是讀文件的線程并沒(méi)有讀出數(shù)據(jù),改變時(shí)間,讀出的數(shù)據(jù)也就各不相同.

         為了避免以上結(jié)果,我們希望在一個(gè)線程在操作某個(gè)文件的時(shí)候,其他線程不能對(duì)該文件進(jìn)行讀或?qū)懖僮?要怎么才能實(shí)現(xiàn)呢?利用java提供的synchronized似乎無(wú)法完成,因?yàn)槊總€(gè)線程是在程序中動(dòng)態(tài)拋出的.郁昧了一天之后,我終于找到了一個(gè)解決辦法,就是利用java.nio包中的FileChannel對(duì)文件進(jìn)行加鎖.

         具體實(shí)現(xiàn)方法如下:

1.寫(xiě)文件的線程

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();
                        
            
//對(duì)該文件加鎖
            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(
"有其他線程正在操作該文件,當(dāng)前線程休眠1000毫秒");
                    sleep(
100);
                }

            }

        
            
for(int i=1;i<=1000;i++){
                sleep(
10);
                StringBuffer sb
=new StringBuffer();
                sb.append(
"這是第"+i+"行,應(yīng)該沒(méi)啥錯(cuò)哈 ");
                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(
"寫(xiě)文件共花了"+(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(
"有其他線程正在操作該文件,當(dāng)前線程休眠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.分別啟用兩個(gè)線程

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

4.結(jié)果分析

以上程序在對(duì)一個(gè)文件執(zhí)行寫(xiě)操作前,先對(duì)該文件加鎖,這樣其他線程就不能再對(duì)該文件操作,等該線程的寫(xiě)操作結(jié)束,釋放資源,其他線程才可以繼續(xù)對(duì)該文件執(zhí)行相應(yīng)的讀寫(xiě)操作.

可是,郁昧的是,這段程序在windows下可以正確執(zhí)行,在linux下卻無(wú)效.根據(jù)<Thinking in Java>上的觀點(diǎn)是:對(duì)獨(dú)占鎖或者共享鎖的支持必須由底層的操作系統(tǒng)提供.

          綜觀我的解決方法,總感覺(jué)不太完美,各位如有好的方法來(lái)判斷一個(gè)文件是否正被某個(gè)線程使用,希望大家一起分享一下.



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1440226

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多