2011-12-22 11 views
29

Se hai mai usato un software di download p2p, puoi scaricare un file con multi-threading e hanno creato un solo file, quindi mi chiedo come i thread scrivano i dati in quel file. Sequenzialmente o in parallelo?È possibile che più thread scrivano dati in un file contemporaneamente?

Immagina di voler scaricare una grande tabella di database in un file e come velocizzare questo lavoro?

+13

Sì, possono, ma si vuole davvero evitare di farlo esattamente nello stesso momento. Ci deve essere un po 'di coordinamento. Se parli di Bittorrent, penso che funzioni assemblando blocchi di offset noti in un file di dimensioni note. Ciò non può essere chiamato sequenzialmente o parallelamente, è più "accesso casuale". – Thilo

+0

Domanda simile: http://stackoverflow.com/questions/6206472/what-is-the-best-way-to-write-to-a-file-in-a-parallel-thread-in-java – Vadzim

risposta

21

È possibile utilizzare più thread scrivendo a in un file, ad es. un file di registro. ma devi coordinare i tuoi thread come @Thilo sottolinea. O è necessario sincronizzare l'accesso ai file e scrivere solo interi record/linee, oppure è necessario disporre di una strategia per allocare regioni del file a thread diversi, ad es. ricostruire un file con offset e dimensioni noti.

Questa operazione viene eseguita raramente per motivi di prestazioni poiché la maggior parte dei sottosistemi del disco ha il rendimento migliore quando viene scritta in sequenza e l'IO del disco è il collo di bottiglia. Se la CPU crea il record o la riga di testo (o IO di rete) è il collo di bottiglia che può aiutare.

Immagine in cui si desidera scaricare una grande tabella di database in un file e come rendere questo lavoro più veloce?

Scriverlo in sequenza è probabilmente il più veloce.

+0

Usa un semaforo –

0

È possibile scrivere più thread sullo stesso file, ma uno alla volta. Tutti i thread dovranno inserire un blocco sincronizzato prima di scrivere sul file.

Nell'esempio P2P, un modo per implementarlo è trovare la dimensione del file e creare un file vuoto di quelle dimensioni. Ogni thread sta scaricando diverse sezioni del file - quando hanno bisogno di scrivere entrano in un blocco sincronizzato - sposta il puntatore del file usando cerca e scrive il contenuto del buffer.

+0

"Tutti i thread dovranno inserire un blocco sincronizzato prima di scrivere sul file.". Beh, loro non hanno * per *. Ma non ti piacerà l'uscita, che potrebbe essere interlacciata in modi divertenti. – Thilo

1

Che tipo di file è questo? Perché hai bisogno di nutrirlo con più thread? Dipende dalle caratteristiche (non conosco una parola migliore) sull'utilizzo del file.

Trasferimento di un file da diversi luoghi sulla rete (a breve: Torrent-like)

Se si sta trasferendo un file esistente, il programma dovrebbe

  • non appena, come si arriva conoscere la dimensione del file, creala con un contenuto vuoto: questo previene errori successivi fuori disco (se non c'è abbastanza spazio, verrà fuori alla creazione, prima di scaricarne qualcosa), inoltre aiuta le prestazioni;
  • se si organizza bene il trasferimento (e perché no), ogni thread sarà responsabile di una parte distinta del file, quindi le scritture dei file saranno distinte,
  • anche se in qualche modo due thread scelgono la stessa porzione del file, non causerà errori, perché scrivono gli stessi dati per le stesse posizioni dei file.

Aggiunta di blocchi di dati in un file (breve: logging)

Se i thread accoda solo informazioni fisse o varie-lenght in un file, è necessario utilizzare un filo comune. Dovrebbe utilizzare un buffer di scrittura relativamente grande, in modo che possa servire i thread dei client in modo rapido (prendendo semplicemente le stringhe) e svuotarlo della pianificazione ottimale e delle dimensioni del blocco. Dovrebbe usare un disco dedicato o persino un computer.

Inoltre, ci possono essere diversi problemi di prestazioni, ecco perché ci sono i server di registrazione in giro, anche quelli commerciali costosi.

Lettura e scrittura tempo casuale, posizione casuale (breve: database)

Richiede disegno complesso, con mutex ecc, non ho mai fatto questo genere di cose, ma posso immaginare. Chiedi ad Oracle alcuni trucchi :)

2

La dichiarazione sincronizzata consente di farlo. Prova il codice seguente che uso in un contesto simile.

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); 
     } 
    } 
} 
Problemi correlati