2011-12-22 64 views
29

如果你曾經使用p2p下載軟件,他們可以下載一個帶有多線程的文件,並且他們只創建一個文件,所以我想知道線程如何將數據寫入該文件。按順序還是並行?多個線程可以同時將數據寫入文件嗎?

想象一下,您要將大型數據庫錶轉儲到文件中,以及如何使此作業更快?

+13

是的,他們可以,但你真的想要避免他們在同一時間做這件事。需要有一些協調。如果你在談論Bittorrent,我認爲這是通過將已知偏移塊組裝成已知大小的文件來工作的。這不能被順序或並行調用,它更「隨機訪問」。 – Thilo 2011-12-22 10:22:40

+0

相似問題:http://stackoverflow.com/questions/6206472/what-is-the-best-way-to-write-to-a-file-in-a-parallel-thread-in-java – Vadzim 2015-06-11 12:57:46

回答

21

您可以使用多個線程將a寫入文件,例如一個日誌文件。但你必須像@Thilo指出的那樣協調你的線索​​。您需要同步文件訪問權限並只寫入整個記錄/行,或者您需要有一種將文件區域分配給不同線程的策略,例如,重建一個已知偏移和大小的文件。

由於性能方面的原因,這很少執行,因爲大多數磁盤子系統在順序寫入時性能最佳,而磁盤IO是瓶頸。如果CPU創建記錄或文本行(或網絡IO)是它可以提供幫助的瓶頸。

想要將大型數據庫錶轉儲到文件的圖像以及如何使此作業更快?

順序書寫它可能是最快的。

+0

使用信號量 – 2017-03-28 20:41:46

0

您可以將多個線程寫入同一個文件 - 但每次只寫一個。在寫入文件之前,所有線程都需要輸入一個同步塊。

在P2P示例中 - 實現它的一種方式是查找文件的大小並創建一個具有該大小的空文件。每個線程正在下載文件的不同部分 - 當他們需要寫入時,他們將進入一個同步塊 - 使用seek移動文件指針並寫入緩衝區的內容。

+0

「在寫入文件之前,所有線程都需要輸入同步塊。」那麼,他們不*有*。但是你不會喜歡那個輸出,那可能會以有趣的方式交錯。 – Thilo 2011-12-22 10:27:57

1

這是什麼類型的文件?爲什麼你需要用更多的線程餵它?這取決於特徵(我不知道更好的詞)它的文件使用情況。

通過網絡從幾個地方傳輸文件(簡稱:洪流般)

如果您是轉移現有的文件,程序應

  • 儘快,因爲它得到知道使用空的內容創建它:這可以防止以後出現磁盤外的錯誤(如果沒有足夠的空間,則在創建之前,在下載任何內容之前會發生這種錯誤),也有助於提高性能;
  • 如果你組織好傳輸(爲什麼不),每個線程將負責文件的不同部分,因此文件寫入將是不同的,即使某種方式兩個線程選擇文件的相同部分,它不會導致錯誤,因爲它們爲相同的文件位置寫入相同的數據。

追加數據塊到文件(簡稱:日誌)

如果線程只是附加固定或各種-lenght信息到一個文件,你應該使用一個共同的主線。它應該使用一個相對較大的寫入緩衝區,因此它可以快速服務客戶端線程(只取得字符串),並將其排除在最佳調度和塊大小之外。它應該使用專用磁盤甚至電腦。

此外,可能會有幾個性能問題,這就是爲什麼有日誌服務器左右,甚至是昂貴的商業。

讀取和寫入任意時間,任意位置(簡稱:數據庫)

它需要複雜的設計,與互斥體等等,我從來沒有這樣做有點東西,但我可以想像的。向Oracle詢問一些技巧:)

2

同步聲明可以做到這一點。嘗試下面的代碼,我在類似的情況下使用。

package hrblib; 

import java.io.*; 

public class FileOp { 

    static int nStatsCount = 0; 

    static public String getContents(String sFileName) { 

     try { 
      BufferedReader oReader = new BufferedReader(new FileReader(sFileName)); 
      String sLine, sContent = ""; 
      while ((sLine=oReader.readLine()) != null) { 
       sContent += (sContent=="")?sLine: ("\r\n"+sLine); 
      } 
      oReader.close(); 
      return sContent; 
     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Invalid file path/File cannot be read: \n" + sFileName); 
     } 
    } 
    static public void setContents(String sFileName, String sContent) { 
     try { 
      File oFile = new File(sFileName); 
      if (!oFile.exists()) { 
       oFile.createNewFile(); 
      } 
      if (oFile.canWrite()) { 
       BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName)); 
       oWriter.write (sContent); 
       oWriter.close(); 
      } 
     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Invalid folder path/File cannot be written: \n" + sFileName); 
     } 
    } 
    public static synchronized void appendContents(String sFileName, String sContent) { 
     try { 

      File oFile = new File(sFileName); 
      if (!oFile.exists()) { 
       oFile.createNewFile(); 
      } 
      if (oFile.canWrite()) { 
       BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName, true)); 
       oWriter.write (sContent); 
       oWriter.close(); 
      } 

     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Error appending/File cannot be written: \n" + sFileName); 
     } 
    } 
} 
相關問題