2011-09-29 67 views
3

我想處理某個FTP目錄,其中包含多個目錄,而這些目錄又有任意數量的文件。所以我想要做的是有1個線程每個子目錄,每個線程各子-DIR在這裏所關心的是我想出了:多線程FTP下載

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(); 
    } 
} 

代碼的順序版本作品 - 我可以看到以.gbk結尾的文件實際上被下載,而多線程版本只創建了相應的子目錄,但沒有下載文件。我甚至沒有任何錯誤。 FTP可能一次不支持多個文件下載?

+0

但每個線程使用相同的FTP連接或打開一個單獨的連接? – gd1

+0

使用相同的連接。這就是爲什麼我說我沒有現在如果FTP作爲協議支持這個 – LordDoskias

+4

通過線程?我非常懷疑它會。所有線程將共享相同的客戶端(因此也是相同的命令通道),並且FTP無法提供執行所需的多路複用的方法,以使其工作。 (對兩條線程的命令的響應看起來差不多; FTP沒有辦法說「這是對命令1的響應」。) – cHao

回答

3

更好的方法是讓其自己的客戶端連接到服務器並創建要下載的文件的路徑列表。然後啓動一些線程,每個線程都有自己的客戶端,從列表中抓取第一個線程並開始下載文件。

您可以擁有一個ftp服務器的併發連接數受限於該服務器的設置。

1

我非常懷疑這可以與多個線程一起工作。所有線程將共享相同的客戶端(因此也是相同的命令通道),並且FTP無法提供執行所需的多路複用的方法,以使其工作。 (對兩條線程的命令的響應看起來差不多; FTP沒有辦法說「這是對命令1的響應」。)

你必須讓每個線程在發送命令之前先獲取一個鎖並且只有在獲得響應後才能解鎖......一次強制執行一條命令,然後序列化事物以至於無論如何都會失去多線程的所有好處。唯一的解決辦法是每個線程使用一個客戶端,但是最終你會遇到每個用戶的連接限制(通常非常嚴格)。

總之,這聽起來像是一個單線程的工作。