2011-09-29 6 views
3

J'essaye de traiter un certain répertoire FTP qui contient plusieurs répertoires et à leur tour, ces répertoires ont un nombre arbitraire de fichiers. Donc ce que je suis en train de faire est d'avoir 1 fil pour chacun des sous-répertoires et chaque thread à se préoccuper de la sous-dir ici est ce que je suis venu respectif:Téléchargement FTP multithread

private void fetchFilesFromFTP() { 

    try { 
     client.connect("ftp.ncbi.nih.gov"); 
     client.login("anonymous", "anonymous"); 

     client.changeWorkingDirectory("genomes/Fungi"); 

     FTPFile dirs[] = client.listDirectories(); 
     dirsToDl.addAndGet(dirs.length); 

     for (final FTPFile ftpFile : dirs) { 
      exec.execute(new Runnable() { 
       //process each FTP directory in a new thread 
       @Override 
       public void run() { 
        processFTPdir(ftpFile.getName()); 
       } 
      }); 
     } 
    } catch (SocketException ex) { 
     Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (IOException ex) { 
     Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

private void processFTPdir(String dir) { 

    File f = new File(destination + File.separator + dir); 
    if (!f.mkdirs()) { 
     System.out.println("Error creating dir for " + dir); 
     return; 
    } 

    FTPFile files[]; 
    try { 
     //we are already in the correct directory 
     files = client.listFiles(dir, new FTPFileFilter() { 

      @Override 
      public boolean accept(FTPFile ftpf) { 
       return ftpf.getName().endsWith(".gbk"); 
      } 
     }); 

     for (FTPFile fTPFile : files) { 
      FileOutputStream fout = new FileOutputStream(destination + File.separator + dir + File.separator + fTPFile.getName()); 
      if (client.retrieveFile(dir + "/" + fTPFile.getName(), fout)) { 

       System.out.println("successfully downloaded"); 
       fout.flush(); 
       fout.close(); 
      } 
      System.out.println(client.getReplyString()); 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex); 
    } finally { 
     if(dirsToDl.decrementAndGet() == 0) latch.countDown(); 
    } 
} 

La version séquentielle du code works - Je peux voir les fichiers se terminant par .gbk en cours de téléchargement alors qu'avec la version multithread, seuls les sous-répertoires respectifs sont créés mais aucun fichier n'est téléchargé. Je n'ai même pas d'erreurs. Est-il possible que FTP ne supporte pas plusieurs téléchargements de fichiers à la fois?

+0

Mais chaque thread utilise la même connexion FTP ou ouvre une connexion distincte? – gd1

+0

utilise la même connexion. C'est pourquoi j'ai dit que je ne l'ai pas fait maintenant si FTP en tant que protocole supportait ce – LordDoskias

+4

Via les threads? J'en doute fortement. Tous les threads partageraient le même client (et donc le même canal de commande), et FTP ne fournit pas un moyen de faire le type de multiplexage dont vous auriez besoin pour le faire fonctionner. (Les réponses aux commandes de deux threads ressemblent à peu près au même: FTP ne peut pas dire "c'est une réponse à la commande 1".) – cHao

Répondre

3

Un meilleur moyen est d'avoir une bande de roulement avec son propre client se connecter au serveur et créer une liste de chemins des fichiers que vous souhaitez télécharger. Ensuite, vous démarrez un certain nombre de threads, chacun avec son propre client, qui récupère le premier de la liste et commence à télécharger le fichier.

Le nombre de connexions simultanées que vous pouvez avoir avec un serveur ftp est limité par les paramètres de ce serveur.

1

Je doute fortement que cela fonctionne avec plusieurs threads. Tous les threads partageraient le même client (et donc le même canal de commande), et FTP ne fournit pas un moyen de faire le type de multiplexage dont vous auriez besoin pour le faire fonctionner. (Les réponses aux commandes de deux threads ressemblent à peu près au même: FTP ne peut pas dire "Ceci est une réponse à la commande 1".)

Chaque thread doit être verrouillé avant d'envoyer une commande et débloquez seulement après avoir reçu une réponse ... en forçant une commande à la fois à courir, et en sérialisant les choses tellement que vous perdriez tous les avantages du multithreading de toute façon. La seule façon de contourner cela serait d'utiliser un client par thread, mais vous finirez par atteindre les limites de connexion par utilisateur (qui ont tendance à être assez strictes). Dans l'ensemble, cela ressemble à un travail pour un seul fil.

Questions connexes