当一个线程访问方法时,如何防止其他线程访问方法?

时间:2010-05-19 14:40:04

标签: java multithreading

我想在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);
       }
    }
}

5 个答案:

答案 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);
       }
    }
}

这不太理想,但它应该给我们一个关于你的代码正在做什么的提示。

如果这些都不起作用,那么您的通用编程逻辑可能是错误的,问题可能与同步无关。