title: How to copy files with multiple process fast
body: <p>I'm creating a game which copies its files at the beginning to AppData/Local(videos,images) and ProgramData(game exe). To make this process fast, the program uses multiple threads to copy various files simultaneously using <code>Files.copy()</code>, "saving time" . Nevertheless, despite using multiple threads, the program copies the files sequentialy and it takes 20-30 seconds. How can I copy files faster, is anything wrong with how I handle threads or is the method <code>Files.copy()</code> itself?</p>
  
  <p><strong>Recap -</strong> <em>I need:</em></p>
  
  <ul>
  <li>The copying process been completed in less than 10 seconds.</li>
  <li>To copy multiple files simultaneously.</li>
  </ul>
  
  <p><strong>Code:</strong></p>
  
  <pre><code>import javax.swing.JFrame;
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.nio.file.StandardCopyOption;
  import java.util.ArrayList;
  import java.util.Set;
  
  /**
   *
   * @author Steve
   */
  
  class Installer extends JFrame {
  
    static Installer installer;
    static int counter, threads;
    static boolean goOn, result, analize;
    static String genericTo, exeTo;
    static String paths [][] = {
        {
            "introVideo",
            "Save Me",
            "Singularity",
            "Fake Love",
            "ON",
            "DNA",
            "Black Swan"
        },
        {
            "playOff",
            "playOn",
            "instructionsOff",
            "instructionsOn",
            "menuOff",
            "menuOn",
            "icon",
            "menu"
        },
        {
            "HyperDance - BTS"
        }
    };
  
      public Installer () {
          //Initiates Instaler UI
          setSize(550,300);
          setResizable(false);
          setLocationRelativeTo(null);
          setVisible(true);
          setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
      }
  
      static void install () {
          //Creates Instaler UI
          installer = new Installer();
          goOn = true;
  
          try {
              //Temp files are cretaed to locate directories (ProgramData &amp; AppData)
              File programData  = File.createTempFile("~$HyperDance", ".tmp", new File("C:/ProgramData"));
              File appDataLocal = File.createTempFile("~$HyperDance", ".tmp", new File("C:/Users/Steve/AppData/Local"));
              programData.deleteOnExit();
              appDataLocal.deleteOnExit();
              System.out.println(programData.getAbsolutePath());
              System.out.println(appDataLocal.getAbsolutePath());
  
              String [] directories = {"\\BTS\\images","\\BTS\\videos","\\BTS\\exe"}; 
              //Floders to save the files are created
              for (int i=0; i&lt;directories.length; i++) {
                  if (i&lt;=1&amp;&amp;Files.notExists(Paths.get(programData.getParent().concat(directories[i])))) {
                      new File(programData.getParent().concat(directories[i])).mkdirs();
                  }
                  if (i&gt;1&amp;&amp;Files.notExists(Paths.get(appDataLocal.getParent().concat(directories[i])))) {
                      new File(appDataLocal.getParent().concat(directories[i])).mkdirs();
                  }
              }
  
              File [][] files = new File[3][7];
                  files[1] = new File[8];
                  files[2] = new File[1];
              genericTo = new File(programData.getAbsolutePath()).getParent().concat("\\BTS");
              exeTo = new File(appDataLocal.getAbsolutePath()).getParent().concat("\\BTS");
              System.out.println(genericTo);
              System.out.println(exeTo+"\n");
  
              long startTime = System.nanoTime();
  
              System.out.println("Copying process started");
              //Files are copied to the created folders
              for (int i=0; i&lt;files.length; i++) {
                  for (int j=0; j&lt;files[i].length; j++) {
                      final int k=i, n=j;
                      Thread copyFiles = new Thread () {
                        @Override
                          public void run () {
                              String [] extension = {".mp4",".png",".exe"}, folder = {"videos","images","exe"};
                              files[k][n] = k&lt;=1? new File(genericTo.concat("\\"+folder[k]+"\\"+paths[k][n]+extension[k])) :
                                                  new File(exeTo.concat("\\"+folder[k]+"\\"+paths[k][n]+extension[k]));
                              if (!files[k][n].exists()) {
                                  switch (k) {
                                      case 0: copy(folder[k], paths[k][n], extension[k], true); break;
                                      case 1: copy(folder[k], paths[k][n], extension[k], true); break;
                                      case 2: copy(folder[k], paths[k][n], extension[k], false); break;
                                  }
                              }
                          }
                      };
                      copyFiles.setName("copyFiles");
                      copyFiles.start();
                  }
              }
  
              Set&lt;Thread&gt; threadSet = Thread.getAllStackTraces().keySet();
              //Starts game if all threads incharged of copying are dead
              Thread startGame = new Thread(){
                @Override
                  public void run () {
                      setUp:
                      while (goOn) {
                          int p = 0;
                          ArrayList &lt;Boolean&gt; threadStatus = new ArrayList&lt;&gt;();
                          for (Thread thread : threadSet) {
                              if (thread.getName().equals("copyFiles")) {
  
                                  p++;
                                  threadStatus.add(!thread.isAlive());
                                  System.out.println(!thread.isAlive() + " " +p);
  
                                  if (p&gt;threads) {
                                      threads = p;
                                  }
                                  else {
                                      analize = true;
                                  }
  
                                  if (analize&amp;&amp;threadStatus.size()==threads) {
                                      if (allThreadsDied(threadStatus,0,threads-1)) {
                                          System.out.println("setUp finished");
                                          Installer.installer.dispose();
  
                                          //Core constructor is called
                                          Core.core = new Core();
                                          //Intro constructor is called
                                          Core.intro = new Intro();
                                            Core.core.add(Core.intro);
                                            Intro.playVideo();
  
                                          long endTime   = System.nanoTime();
                                          long totalTime = endTime - startTime;
                                          double time = (double) totalTime / 1_000_000_000;
                                          System.out.println(time);
  
                                          goOn = false;
                                          break setUp;
                                      }
                                      threadStatus.clear();
                                  } 
                              }    
                          }
                          System.out.println("\n");
                      }   
                  }
              };
              startGame.start();
          }
          catch (IOException ex) {}
      }
  
      /**
       Returns true if copying threads are dead
       */
      synchronized static boolean allThreadsDied (ArrayList &lt;Boolean&gt; threadStatus, int p, int threads){
          if (threadStatus.get(p)==true) {
              if (p&lt;threads) {
                  allThreadsDied(threadStatus, p+1, threads);
              }
              else{
                  result = true;
              }
          }
          return result; 
      }
  
      /**
       Copies files to given directories
       */
      static void copy (String folder, String file, String extension, boolean toProgramData) {
          InputStream from = new Object().getClass().getResourceAsStream("/media/"+folder+"/"+file+extension);
          String to;
          try {
              to = toProgramData? genericTo.concat("\\"+folder+"\\"+file+extension) : exeTo.concat("\\"+folder+"\\"+file+extension);
              System.out.println(to);
              Files.copy(from,Paths.get(to), StandardCopyOption.REPLACE_EXISTING);
          } catch (IOException e) {}
      }
  }
  </code></pre>