我想在10个文件中搜索一个字符串,并将匹配的行写入单个文件。我将每个文件的匹配行写入10个输出文件(o / p file1,o / p file2 ...),然后使用10个线程将这些文件复制到单个文件中。
但是输出单个文件有混合输出(来自o / p file1的一行,来自o / p file 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);
}
}
}
答案 0 :(得分:3)
public synchronized void method() {
}
在您存在方法之前,请确保flush()
/ close()
所有流。
并且,如Xavier的评论中所述,请确保在同一实例上调用该方法。因为同步发生在每个实例(在这种情况下)
答案 1 :(得分:2)
如果我理解这一点,你想阻止两个线程写入同一个文件吗?
最简单的方法是锁定文件本身,而不是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();
}
答案 2 :(得分:0)
源代码:
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);
}
}
答案 3 :(得分:0)
如果有一个带锁的文件编写器类(即获取实例上的锁,执行必要的写操作,然后释放锁;有点像数据库事务)?考虑将文件编写器的实例传递给需要执行写入的对象/方法(还有更容易进行单元测试/模拟的额外好处)。
答案 4 :(得分:0)
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);
}
}
}
这不太理想,但它应该给我们一个关于你的代码正在做什么的提示。
如果这些都不起作用,那么您的通用编程逻辑可能是错误的,问题可能与同步无关。