2011-09-29 70 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的响应”。)

你必须让每个线程在发送命令之前先获取一个锁并且只有在获得响应后才能解锁......一次强制执行一条命令,然后序列化事物以至于无论如何都会失去多线程的所有好处。唯一的解决办法是每个线程使用一个客户端,但是最终你会遇到每个用户的连接限制(通常非常严格)。

总之,这听起来像是一个单线程的工作。