2011-09-29 7 views
3

여러 개의 디렉토리를 보유하고있는 특정 FTP 디렉토리를 처리하려고하는데, 그 디렉토리에는 임의의 수의 파일이 있습니다. 그래서 내가 할 노력하고있어 것은 1 개 서브 디렉토리의 각 스레드 여기에 각각의 하위 디렉토리와 관련되는 각 스레드를 가질 것은 내가 해낸 것입니다 :멀티 스레드 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-server에 대해 가질 수있는 동시 연결 수는 해당 서버의 설정에 따라 제한됩니다.

1

나는 이것이 여러 스레드에서 작동 할 것입니다. 모든 스레드는 동일한 클라이언트 (따라서 동일한 명령 채널)를 공유하며 FTP는 작동시키기 위해 필요한 멀티플렉싱 종류를 수행하는 방법을 제공하지 않습니다. (두 스레드의 명령에 대한 응답은 거의 같습니다. FTP가 "명령 1에 대한 응답입니다."라고 말할 수있는 방법이 없습니다.)

명령을 보내기 전에 각 스레드가 잠금을 잡아야합니다 응답을 얻은 후에 만 ​​잠금을 해제하고, 한 번에 하나의 명령을 실행하도록 강제하고, 여러 가지를 직렬화하여 어쨌든 멀티 스레딩의 모든 이점을 잃을 수 있습니다. 주위의 유일한 방법은 스레드 당 클라이언트를 사용하는 것이지만 사용자 별 연결 제한 (꽤 엄격한 경향이 있음)으로 끝납니다.

모두 하나의 스레드에 대한 작업처럼 들립니다.