2016-07-14 11 views
2

Ich bin neu in Java gleichzeitige API und ich habe gesucht, aber keine Antwort auf meine Frage gefunden.Warum stoppen die Threads, wenn der andere startet?

Nun, ich habe einen Code, der nach jeder Datei innerhalb von Verzeichnissen und deren Unterverzeichnissen sucht und ein anderes, das jede gefundene Datei kopiert, die einem bestimmten Muster entspricht.

Ich trenne diese Codes in einer Runnable Implementierung genannt DirSearch und eine aufrufbare Implementierung genannt Filesearch und legt sie eine ExecutorService verwenden.

, dass der Code ist:

private boolean execute() { 
    ExecutorService executor = Executors.newFixedThreadPool(threadsNumber); 
    BlockingQueue<File> dirQueue = new LinkedBlockingQueue<>(); 
    BlockingQueue<File> fileQueue = new LinkedBlockingQueue<>(10000); 

    boolean isFinished = false; 

    try { 
     for(int i = 0; i < dirThreads; i++) { 
      executor.submit(new DirSearch(dirQueue, fileQueue, count, dirThreads); 
     } 

     count.incrementAndGet(); 
     dirQueue.add(baseDir); 

     Future<Boolean> future = executor.submit(new FileSearch(filequeue, outputDirectory, filename)); 

     isFinished = future.get(); 
    } catch(ExecutionException | InterruptedException | RuntimeException ex) { 
     ex.printStackTrace(); 
    } finally { 
     executor.shutdownNow(); 
    } 

    return isFinished; 
} 

... 

private void copyFile(File in, File out) { 
    Path inPath = Paths.get(in.getAbsolutePath()); 
    Path outPath = Paths.get(out.getAbsolutePath(), in.getName()); 

    try { 
     main.updateCurrentLabel(outPath.toString()); 

     switch(mode) { 
      case "1": 
       Files.copy(inPath, outPath, StandardCopyOption.REPLACE_EXISTING); 
       break; 
      case "2": 
       Files.move(inPath, outPath, StandardCopyOption.REPLACE_EXISTING); 
       break; 
      default: 
       break; 
     } 

     main.updateCopiedLabel(String.valueOf(countCpFiles.incrementAndGet())); 
    } catch(IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

... 

private class DirSearch implements Runnable { 

    ... 

    @Override 
    public void run() { 
     try { 
      File dir = dirQueue.take(); 

      while(dir != new File("")) { 
       File[] elements = dir.listFiles(); 

       if(elements != null) { 
        for(File element : elements) { 
         if(element.isDirectory()) { 
          count.incrementAndGet(); 
          dirQueue.put(element); 
         } else { 
          fileQueue.put(element); 
         } 
        } 
       } 

       if(count.decrementAndGet() == 0) { 
        end(); 
       } 

       dir = dirQueue.take(); 
      } 
     } catch(InterruptedException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    ... 

} 

... 

private class FileSearch implements Callable<Boolean> { 

    ... 

    @Override 
    public Boolean call() { 
     boolean isFinished = false; 

     try { 
      File file = fileQueue.take(); 

      while(file != new File("")) { 
       incrementAnalyzed(); 
       String foundFile = file.getName().toLowerCase(); 

       if(foundFile.matches(filename.replace("?", ".?").replace("*", ".*?"))) { 
        copyFile(file, outputDirectory); 
       } 

       file = fileQueue.take(); 
      } 

      isFinished = true; 
     } catch(InterruptedException ex) { 
      ex.printStackTrace(); 
     } 

     return isFinished; 
    } 
} 

Das Problem ist: Wenn die Filesearch Startdateien zu kopieren, die anderen Threads (DirSearch) stoppen und schauen Sie nicht für jede neue Datei, bis die Kopie abgeschlossen. Warum passiert das? Mache ich etwas falsch oder ist das nicht der richtige Ansatz?

+3

Was sind die Werte von 'dirThreads' und' threadsNumber'? –

+0

Beachten Sie, dass 'dir! =" "' Nicht kompiliert wird. –

+0

@AndyTurner Die _threadsNumber_ ist eine Eingabe vom Benutzer und _dirThreads_ ist ThreadNumber - 1. Ich schrieb das ganze von Hand, weil es nicht im selben Computer ist, es ist mein Fehler der dir! = "". Überprüfen Sie die bearbeitete Frage. –

Antwort

-1

Zwei mögliche Antworten, die mir in den Sinn kamen und die ich nicht garantieren kann: 1. Java VM bekommt nur einen Kern von Ihrer CPU, was bedeutet, dass nur ein Thread gleichzeitig ausgeführt werden kann. 2. Ihre Threads verwenden beide die gleiche Variable, was bedeutet, dass nur einer es wirklich gleichzeitig manipulieren darf. Suchen Sie für dieses spezielle Problem Java-Schlüsselwort "synchronisiert". Ich vermute, die Wurzel des Problems ist die # 1