我想處理某個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可能一次不支持多個文件下載?
但每個線程使用相同的FTP連接或打開一個單獨的連接? – gd1
使用相同的連接。這就是爲什麼我說我沒有現在如果FTP作爲協議支持這個 – LordDoskias
通過線程?我非常懷疑它會。所有線程將共享相同的客戶端(因此也是相同的命令通道),並且FTP無法提供執行所需的多路複用的方法,以使其工作。 (對兩條線程的命令的響應看起來差不多; FTP沒有辦法說「這是對命令1的響應」。) – cHao