2017-02-21 129 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對象出現故障(我認爲它不是有意的) 。