繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM