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

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

在最近的工作中,经常要用到线程,就对线程相关知识稍微看了看,知道并发线程经常引起共享资源冲突,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 ... {
publicvoidrun()...{
Calendarcalstart
=Calendar.getInstance();
Filefile
=newFile("D:/test.txt");
try...{
if(!file.exists())
file.createNewFile();
FileWriterfw
=newFileWriter(file);
BufferedWriterbw
=newBufferedWriter(fw);
for(inti=0;i<1000;i++)...{
sleep(
10);
bw.write(
"这是第"+(i+1)+"行,应该没错哈 ");
}

bw.close();
bw
=null;
fw.close();
fw
=null;
}
catch(IOExceptione)...{
e.printStackTrace();
}
catch(InterruptedExceptione)...{
e.printStackTrace();
}

Calendarcalend
=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 ... {
publicvoidrun()...{
try...{
Calendarcalstart
=Calendar.getInstance();
sleep(
5000);
Filefile
=newFile("D:/test.txt");
BufferedReaderbr
=newBufferedReader(newFileReader(file));
Stringtemp
=null;
temp
=br.readLine();
while(temp!=null)...{
System.out.println(temp);
temp
=br.readLine();
}


br.close();
br
=null;
Calendarcalend
=Calendar.getInstance();
System.out.println(
"读文件共用了"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"毫秒");
}
catch(FileNotFoundExceptione)...{
e.printStackTrace();
}
catch(IOExceptione)...{
e.printStackTrace();
}
catch(InterruptedExceptione)...{
e.printStackTrace();
}

}

}

3.分别启用两个线程

Thread_writeFilethf3 = new Thread_writeFile();
Thread_readFilethf4
= 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;

/***/ /**
*
@authorchb
*
*/

public class Thread_writeFile extends Thread ... {
publicvoidrun()...{
Calendarcalstart
=Calendar.getInstance();
Filefile
=newFile("D:/test.txt");
try...{
if(!file.exists())
file.createNewFile();

//对该文件加锁
FileOutputStreamout=newFileOutputStream(file,true);
FileChannelfcout
=out.getChannel();
FileLockflout
=null;
while(true)...{
flout
=fcout.tryLock();
if(flout!=null)...{
break;
}

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

}


for(inti=1;i<=1000;i++)...{
sleep(
10);
StringBuffersb
=newStringBuffer();
sb.append(
"这是第"+i+"行,应该没啥错哈 ");
out.write(sb.toString().getBytes(
"utf-8"));
}



flout.release();
fcout.close();
out.close();
out
=null;
}
catch(IOExceptione)...{
e.printStackTrace();
}
catch(InterruptedExceptione)...{
e.printStackTrace();
}

Calendarcalend
=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;

/***/ /**
*
@authorchb
*���ļ�
*/

public class Thread_readFile extends Thread ... {
publicvoidrun()...{
try...{
Calendarcalstart
=Calendar.getInstance();
sleep(
5000);
Filefile
=newFile("D:/test.txt");

//给该文件加锁
FileInputStreamfis=newFileInputStream(file);
FileChannelfcin
=fis.getChannel();
FileLockflin
=null;
while(true)...{
flin
=fcin.tryLock(0,Long.MAX_VALUE,true);
if(flin!=null)...{
break;
}

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

}

byte[]buf=newbyte[1024];
StringBuffersb
=newStringBuffer();
while((fis.read(buf))!=-1)...{
sb.append(
newString(buf,"utf-8"));
buf
=newbyte[1024];
}


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

flin.release();
fcin.close();
fis.close();
fis
=null;

Calendarcalend
=Calendar.getInstance();
System.out.println(
"读文件共花了"+(calend.getTimeInMillis()-calstart.getTimeInMillis())+"");
}
catch(FileNotFoundExceptione)...{
e.printStackTrace();
}
catch(IOExceptione)...{
e.printStackTrace();
}
catch(InterruptedExceptione)...{
e.printStackTrace();
}

}

}

3.分别启用两个线程

Thread_writeFilethf3 = new Thread_writeFile();
Thread_readFilethf4
= new Thread_readFile();
th
分享到:
评论

你可能感兴趣的:(java,thread,多线程,工作)