web-dev-qa-db-fra.com

Plusieurs threads peuvent-ils écrire des données dans un fichier en même temps?

Si vous avez déjà utilisé un logiciel de téléchargement p2p, ils peuvent télécharger un fichier avec plusieurs threads et ils n'ont créé qu'un seul fichier, donc je me demande comment les threads écrivent des données dans ce fichier. Séquentiellement ou en parallèle?

Imaginez que vous souhaitiez vider une grande table de base de données dans un fichier, et comment accélérer ce travail?

31
CaiNiaoCoder

Vous pouvez utiliser plusieurs threads écrivant un dans un fichier, par exemple un fichier journal. mais vous devez coordonner vos discussions comme le souligne @Thilo. Soit vous devez synchroniser l'accès au fichier et écrire uniquement des enregistrements/lignes entiers, soit vous devez avoir une stratégie pour allouer des régions du fichier à différents threads, par exemple recréer un fichier avec des décalages et des tailles connus.

Cela est rarement fait pour des raisons de performances car la plupart des sous-systèmes de disques fonctionnent mieux lorsqu'ils sont écrits de manière séquentielle et le disque IO est le goulot d'étranglement. Si le processeur pour créer l'enregistrement ou la ligne de texte (ou les E/S réseau) est le goulot d'étranglement, il peut aider.

Image que vous souhaitez vider une grande table de base de données dans un fichier, et comment accélérer ce travail?

L'écriture séquentielle sera probablement la plus rapide.

21
Peter Lawrey

Le package Java nio a été conçu pour permettre cela. Jetez un œil par exemple à http://docs.Oracle.com/javase/1.5.0/docs/api/Java/nio/channels/FileChannel.html .

Vous pouvez mapper plusieurs régions d'un fichier à différents tampons, chaque tampon peut être rempli séparément par un thread distinct.

18
WeMakeSoftware

La déclaration synchronisée permet de le faire. Essayez le code ci-dessous que j'utilise dans un contexte similaire.

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);
        }
    }
}
2
Padmakumar

De quel type de fichier s'agit-il? Pourquoi avez-vous besoin de le nourrir avec plus de fils? Cela dépend des caractéristiques (je ne connais pas mieux Word pour cela) de l'utilisation du fichier.

Transfert d'un fichier de plusieurs endroits sur le réseau (court: comme un torrent)

Si vous transférez un fichier existant, le programme devrait

  • dès qu'il connaît la taille du fichier, créez-le avec un contenu vide: cela évite les erreurs de rupture de disque ultérieures (s'il n'y a pas assez d'espace, il se révélera à la création, avant de télécharger quoi que ce soit), cela aide aussi à la performance;
  • si vous organisez bien le transfert (et pourquoi pas), chaque thread sera responsable d'une partie distincte du fichier, ainsi les écritures de fichier seront distinctes,
  • même si en quelque sorte deux threads choisissent la même partie du fichier, cela ne causera aucune erreur, car ils écrivent les mêmes données pour les mêmes positions de fichier.

Ajout de blocs de données à un fichier (abrégé: journalisation)

Si les threads ajoutent simplement des informations fixes ou de longueurs différentes à un fichier, vous devez utiliser un thread commun. Il doit utiliser un tampon d'écriture relativement volumineux, afin de pouvoir servir rapidement les threads clients (en prenant simplement les chaînes) et de le vider de la planification et de la taille de bloc optimales. Il doit utiliser un disque dédié ou même un ordinateur.

De plus, il peut y avoir plusieurs problèmes de performances, c'est pourquoi il y a des serveurs de journalisation autour, même des serveurs commerciaux coûteux.

Lecture et écriture de temps aléatoire, position aléatoire (abrégé: base de données)

Cela nécessite une conception complexe, avec des mutex, etc., je n'ai jamais fait ce genre de choses, mais je peux imaginer. Demandez à Oracle quelques astuces :)

1
ern0

Plusieurs threads peuvent écrire dans le même fichier, mais un à la fois. Tous les threads devront entrer un bloc synchronisé avant d'écrire dans le fichier.

Dans l'exemple P2P - une façon de l'implémenter est de trouver la taille du fichier et de créer un fichier vide de cette taille. Chaque thread télécharge différentes sections du fichier - lorsqu'ils ont besoin d'écrire, ils entreront un bloc synchronisé - déplacer le pointeur de fichier à l'aide de la recherche et écrire le contenu du tampon.

0
gkamal