2017-02-21 142 views
1

我的文件同步阅读有问题。情况很简单:处理文件中的数据。我的问题是同步。我试图使它成为BufferedReader类的对象读取器,但我有两个问题。如果我初始化读者在我的方法read()中的“试用资源”,当我在不同的角色中使用它时,我会得到同一个对象的BufReader的不同对象。第二个我在课堂上初始化它,并获得线程的同一个对象,但是这是一个很大的问题,具有不可预知的行为。我将为第二种情况编写代码。你能告诉我如何解决。我正在学习,这就是为什么我需要建议。多线程的Java问题

class FileReaderClass { 
    private File file = new File("src\\exer1\\Transfers.txt"); 
    private BufferedReader reader = null; 
    private FileReader fr = null; 

    StringBuilder sb = new StringBuilder(); 

    void read() throws IOException { 
     try { 
      fr = new FileReader(file); 
      reader = new BufferedReader(fr); 
      String buftext; 
       while ((buftext = reader.readLine()) != null){ 
        synchronized (reader) { 
         System.out.println(Thread.currentThread().getName());//for testing 
         sb.append(buftext).append("\n"); 
         //System.out.println(buftext); 
        } 
       } 
      } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      if (reader != null) 
       reader.close(); 
      if (fr != null) 
       fr.close(); 
     } 
    } 
} 

class Reader1 implements Runnable { 

    private FileReaderClass frc; 

    public Reader1(FileReaderClass frc) { 
     this.frc = frc; 
    } 

    @Override 
    public void run() { 
     try { 
      frc.read(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
public class Ex1 { 
    public static void main(String[] args) throws InterruptedException { 
     FileReaderClass frc = new FileReaderClass(); 
     Thread t1 = new Thread(new Reader1(frc)); 
     Thread t2 = new Thread(new Reader2(frc)); 

     t1.start(); 
     t2.start(); 
     t1.join(); 
     t2.join(); 
     System.out.println("---------------------"); 
     System.out.println(frc.sb); 

    } 
} 
+0

你想做什么?一次只有一个打开的文件?只有一个同时读取同一个文件? –

+0

是的,我只想现在就读。其他逻辑是下一步。但是我想要读取文件中的一行,而不是一次写入Stringbuilder。我想在几个线程中使它平行。案例是文件的并行处理。 –

+0

在这种情况下,@SelçukCihan是正确的。同步没有意义。你可以尝试使用资源。您创建的每个FileReaderClass都将拥有自己的FileReader,并且它是您想要的。但是为了对文件进行并行处理,我认为你的文件阅读器应该读取文件的不同部分,并且你必须连接最终结果。这会更有意义。 –

回答

0

您在两个线程共享相同FileReaderClass实例(也就是frc)。您的FileReaderClass不是线程安全的,会导致问题。这里有两种选择:

  • 创建FileReaderClass的另一个实例,以便两个线程将使用不同的实例。
  • 将方法read标记为snychronized

您正在同步错误的级别。你的同步警卫没用,因为实际上有两个reader s。这是因为每次调用read时,都会创建一个reader,这将是一个单独的实例。我们甚至无法确定,哪个reader实例是同步的主题。

+0

但是我可以为FileReaderClass制作BufferedReader的通用实例吗?我试图做到这一点,但它会抛出IOExeption。我知道类构造函数中的异常是不好的做法。谢谢您的回答。我明白了。 –

+0

@GuluevRuslan我不确定'BufferedReader'方法是否是线程安全的,所以我不会建议在多线程中同时使用同一个'BufferedReader'实例。你真的需要阅读多线程文件吗?大多数情况下,瓶颈不是读取输入,而是处理实际需要并行化的数据。也许你应该重新考虑并行化输入。 –

0

如果你想并行读你的文件,你应该使用相同的阅读器,但任何线程的每次读取使用适当的同步,以便它保持一致,最简单的方法是使整个读取方法同步并实例化读者在你的类构造函数中。

由于您可能需要按正确的顺序读写字符串生成器,因此读取行的线程必须在写入到StringBuilder后才释放锁,从而使您的整个方法几乎被锁。它会工作,但你不会获得任何表现,对于小文件可能会造成太多的开销,但作为一个练习它可能就足够了。

您的代码,因为它是具有下列问题

  1. 你总是在创造新的读者,因此,每一个线程调用此方法将从头开始。
  2. 如前所述,你正在同步错误的级别,任何线程可能会读取和线程调度程序可以暂停它,导致您的写入到StringBuilder对象出现故障(我认为它不是有意的) 。