title: Using multiple threads to download files using JSch
body: <p>I am trying to download multiple files from a remote server using multiple threads. However when I am using multiple threads I get</p>
  
  <blockquote>
    <p>java.lang.IOException : Pipes closed.</p>
  </blockquote>
  
  <p>The same code works fine when i am using exactly one thread. </p>
  
  <p>Is it not possible to download multiple files simultaneously from the same remote server using JSch?</p>
  
  <p>SftpTest.java</p>
  
  <pre><code>public class SftpTest {
  
  private static List&lt;SftpAccessor&gt; accessorList = new ArrayList&lt;SftpAccessor&gt;();
  private static List&lt;Payload&gt; files = new ArrayList&lt;Payload&gt;();
  private static ExecutorService writerThreadPool = Executors.newFixedThreadPool(10);
  
  public static void main(String args[]) throws JSchException, InterruptedException {
      SSH srcServer = new SSH();
      srcServer.setHostname("10.22.65.140");
      srcServer.setKey("D:\\jars\\dmwvmcol01.ec2user.pem");
      srcServer.setPort("22");
      srcServer.setUsername("ec2-user");
  
      SftpAccessor acc = new SftpAccessor(srcServer);
      accessorList.add(acc);
  
      files.addAll(acc.ls("/data/test/src", false, "*", 1));
  
      for (Payload file : files) {
          writerThreadPool.submit(new LocalWriterThread(file));
      }
  
      writerThreadPool.shutdown();
      writerThreadPool.awaitTermination(20, TimeUnit.MINUTES);
  }}
  </code></pre>
  
  <p>LocalWriterThread.java</p>
  
  <pre><code>public class LocalWriterThread implements Callable&lt;String&gt; {
  
  private Payload payload;
  
  public LocalWriterThread(Payload payload) {
      this.payload = payload;
  }
  
  public String call() throws Exception {
      String dest = "D:\\output\\jobsystemnew";
      System.out.println(payload.getFilename());
      File file = new File(dest + "/" + payload.getFilename());
      file.createNewFile();
      FileOutputStream fos = new FileOutputStream(file);
      copy(payload.getInputStream(), fos);
      payload.setInputStream(null);
      return "";
  }
  
  private void copy(InputStream is, OutputStream os) throws IOException {
  
      BufferedInputStream bis = null;
      BufferedOutputStream bos = null;
      try {
          System.out.println("Started Copying file : " + payload.getFilename());
  
          bis = new BufferedInputStream(is);
          bos = new BufferedOutputStream(os);
  
          byte[] buffer = new byte[1024];
  
          while (bis.read(buffer) != -1) {
              bos.write(buffer);
          }
  
          bos.flush();
          System.out.println("Finished Copying file : " + payload.getFilename());
      }
      finally {
          System.out.println("Closing input stream for " + payload.getFilename());
          bis.close();
          bos.close();
          /*
           * try { if (is != null) { is.close(); } } catch (Exception e) { System.out.println(" " + e + " : " + e.getMessage() + " unable to close input stream : " + payload.getFilename());
           * e.printStackTrace(); }
           */
          /*
           * try { if (os != null) { os.close(); } } catch (Exception e) { System.out.println(" " + e + " : " + e.getMessage() + " unable to close output stream : " + payload.getFilename());
           * e.printStackTrace(); }
           */
      }
  
  }}
  </code></pre>
  
  <p>SSH.java</p>
  
  <pre><code>public class SSH {
  String hostname;
  String port;
  String username;
  String key;
  
  public String getHostname() {
      return hostname;
  }
  public void setHostname(String hostname) {
      this.hostname = hostname;
  }
  public String getPort() {
      return port;
  }
  public void setPort(String port) {
      this.port = port;
  }
  public String getUsername() {
      return username;
  }
  public void setUsername(String username) {
      this.username = username;
  }
  public String getKey() {
      return key;
  }
  public void setKey(String key) {
      this.key = key;
  } }
  </code></pre>
  
  <p>SftpAccessor.java</p>
  
  <pre><code>public class SftpAccessor {
  
  private JSch jsch = new JSch();
  private ChannelSftp channelSftp = null;
  private Session session = null;
  
  String errorMsg = null;
  
  public SftpAccessor(SSH ssh) throws JSchException {
  
      jsch.addIdentity(ssh.getKey());
      session = jsch.getSession(ssh.getUsername(), ssh.getHostname(), Integer.parseInt(ssh.getPort()));
      session.setHostKeyAlias(ssh.getKey());
  
      java.util.Properties config = new java.util.Properties();
      config.put("StrictHostKeyChecking", "no");
      session.setConfig(config);
      session.connect();
      channelSftp = (ChannelSftp) session.openChannel("sftp");
      channelSftp.connect();
  
  }
  
  public List&lt;Payload&gt; ls(String directory, boolean recursive, String filemask, int delayMinutes) {
  
      List&lt;Payload&gt; files = new ArrayList&lt;Payload&gt;();
  
      try {
  
          channelSftp.cd(directory);
  
          @SuppressWarnings("unchecked")
          Vector&lt;ChannelSftp.LsEntry&gt; entries = channelSftp.ls(filemask);
  
          for (ChannelSftp.LsEntry entry : entries) {
              try {
                  if (entry.getAttrs().isDir()) {
                      if (recursive) {
                          List&lt;Payload&gt; filesToAdd = ls(directory + "/" + entry.getFilename(), recursive, filemask, delayMinutes);
                          files.addAll(filesToAdd);
                      }
                  }
                  else {
  
                      Date lastmodified = new Date(entry.getAttrs().getMTime() * 1000L);
                      Date currdate = new Date(new Date().getTime() - (delayMinutes * 60 * 1000L));
  
                      if (lastmodified.before(currdate)) {
                          String filename = entry.getFilename();
                          entry.getAttrs().getMTime();
  
                          Payload file = new Payload();
                          System.out.println("Getting input Stream for " + directory + "/" + filename);
                          file.setInputStream(channelSftp.get(directory + "/" + filename));
                          file.setFilename(filename);
                          file.setLastModified(lastmodified);
                          files.add(file);
                      }
  
                  }
              }
              catch (Exception e) {
                  e.printStackTrace();
              }
          }
  
      }
      catch (SftpException e) {
  
      }       
  
      return files;
  }}
  </code></pre>
  
  <p>Payload.java</p>
  
  <pre><code>public class Payload {
  
  private String filename;
  private InputStream inputStream;
  private Date lastModified;
  
  public String getFilename() {
      return filename;
  }
  
  public void setFilename(String filename) {
      this.filename = filename;
  }
  
  public Date getLastModified() {
      return lastModified;
  }
  
  public void setLastModified(Date lastModified) {
      this.lastModified = lastModified;
  }
  
  public InputStream getInputStream() {
      return inputStream;
  }
  
  public void setInputStream(InputStream inputStream) {
      this.inputStream = inputStream;
  }}
  </code></pre>