[英]How to prevent the other threads from accessing a method when one thread is accessing a method?
我想在10个文件中搜索一个字符串,并将匹配的行写到一个文件中。 我将每个文件的匹配行写到10个输出文件(o / p file1,o / p file2 ...),然后使用10个线程将它们复制到单个文件中。
但是输出单个文件具有混合输出(o / p文件1中的一行,o / p文件2中的另一行等),因为它被许多线程同时访问。 如果我等待所有线程完成,然后写入单个文件,则速度会慢很多。 我希望输出文件一次由一个线程写入。 我该怎么办?
我的源代码:(仅写入单个文件方法)
public void WriteSingle(File output_file,File final_output) throws IOException {
synchronized(output_file){
System.out.println("Writing Single file");
FileOutputStream fo = new FileOutputStream(final_output,true);
FileChannel fi = fo.getChannel();
FileInputStream fs = new FileInputStream(output_file);
FileChannel fc = fs.getChannel();
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = fc.size();
long position = 0;
while (position < size) {
position += fc.transferTo(position, maxCount, fi);
}
}
}
public synchronized void method() {
}
并且在存在该方法之前,请确保先flush()
/ close()
所有流。
并且,如Xavier的注释中所述,请确保在同一实例上调用该方法。 因为同步是按实例进行的(在这种情况下)
如果我理解这一点,是否要阻止两个线程写入同一文件?
最简单的方法是锁定文件本身,而不是File
对象:
public void WriteSingle(File output_file, File final_output) throws IOException {
System.out.println("Writing Single file");
FileOutputStream fo = new FileOutputStream(final_output,true);
FileChannel fi = fo.getChannel();
FileInputStream fs = new FileInputStream(output_file);
FileChannel fc = fs.getChannel();
FileLock lock = fi.lock(); // Get lock here, blocks until file is closed
fc.transferTo(0, fc.size(), fi);
fc.close();
fi.close();
fo.close();
fs.close();
}
源代码:
public void WriteSingle(File output_file,File final_output)
throws IOException
{
synchronized(output_file){
try{
wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Writing Single file");
FileOutputStream fo = new FileOutputStream(final_output,true);
FileChannel fi = fo.getChannel();
FileInputStream fs = new FileInputStream(output_file);
FileChannel fc = fs.getChannel();
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = fc.size();
long position = 0;
while (position < size) {
position += fc.transferTo(position, maxCount, fi);
}
}
拥有一个具有锁定功能的文件编写器类(即在实例上获取锁定,执行必要的写操作,然后释放锁定;有点像数据库事务)会怎么样? 考虑将文件编写器的实例传递给需要执行写入操作的对象/方法(具有更方便的单元测试/模拟的其他好处)。
public synchronized void WriteSingle(File output_file,File final_output) throws IOException {
System.out.println("Writing Single file");
FileOutputStream fo = new FileOutputStream(final_output,true);
FileChannel fi = fo.getChannel();
FileInputStream fs = new FileInputStream(output_file);
FileChannel fc = fs.getChannel();
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = fc.size();
long position = 0;
while (position < size) {
position += fc.transferTo(position, maxCount, fi);
}
}
如果这不起作用,则您可能正在使用多个实例来写入文件。 在这种情况下,您可以尝试这样的类锁:
public void WriteSingle(File output_file,File final_output) throws IOException {
synchronized(getClass()) {
System.out.println("Writing Single file");
FileOutputStream fo = new FileOutputStream(final_output,true);
FileChannel fi = fo.getChannel();
FileInputStream fs = new FileInputStream(output_file);
FileChannel fc = fs.getChannel();
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = fc.size();
long position = 0;
while (position < size) {
position += fc.transferTo(position, maxCount, fi);
}
}
}
这不是理想的方法,但是它应该给我们提示您的代码在做什么。
如果这些都不起作用,则您的常规编程逻辑可能是错误的,并且此问题可能与同步无关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.