2011-07-04 31 views
4

我通過產生5個pngout.exe進程來優化PNG文件以在PNG文件的目錄上工作。由於pngout是單線程的,因此會導致較大的加速。某些圖像需要很長時間才能優化,長達30秒,而標準爲5秒鐘的<。問題:長計算導致ExecutorService停止分配新工作

  • 文件1很大,2-5很小,共有50個文件,但其餘的細節無關緊要。
  • 首先5個PNGOUT過程正常產卵並開始工作
  • 2-5出口在10秒內
  • 1採取45秒
  • 無新PNGOUT過程在此產生了,儘管具有四個螺紋自由
  • 一旦完成1,另外五個過程被產生。

代碼:

private final ExecutorService pool = Executors.newFixedThreadPool(5); 

    /*^instance var, below is in method */ 

    CompletionService<Boolean> comp = new ExecutorCompletionService<Boolean>(pool); 
    List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>(); 
    for (int i = 0; i < files.length; i++) { 
     File infile = files[i]; 
     File outfile = new File(outdir, infile.getName()); 
     tasks.add(new CrushTask(crusher, infile, outfile)); 
    } 
    for (Callable<Boolean> t : tasks) 
     comp.submit(t); 
    for (int i = 0; i < files.length; i++) { 
     try { 
      boolean res = comp.take().get(); 
      System.out.println(res); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

的所有文件都正確的優化,代碼的那部分工作。問題在於,通過等待大圖像,整個過程大大減慢。與單線程時間相比,我只獲得了40%的改進。

我在做什麼錯?

編輯:修復了這個問題,使用了一些非常難看的代碼。問題是,要獲得我產生的進程的退出值(知道它們何時完成,以及它們是否成功),我將它們的stdout讀爲無,因爲調用waitFor將永遠掛起。但是,顯然使用InputStream會導致線程窒息。

因此,要獲得進程的出口值,而不是使用這樣的:

private static int discardStdOut(Process proc) throws IOException { 
    final InputStream is = proc.getInputStream(); 
    try { 
     while (is.read() != -1) 
      continue; 
     return proc.exitValue(); 
    } finally { 
     close(is); 
    } 
} 

我用這總代碼:

private static int discardStdOut(Process proc) { 
    int ret = -1; 
    while (true) { 
     try { 
      ret = proc.exitValue(); 
      break; 
     } catch (IllegalThreadStateException e) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e2) { 
       e2.printStackTrace(); 
      } 
     } 
    } 
    return ret; 
} 

它的毛,但現在系統正常工作並始終有5個進程在運行。

延遲編輯:從here StreamGobbler可能更合適。

+0

文件變量的定義是什麼?它是完整的50個文件嗎? –

+0

files變量是一個包含全部50個輸入PNG文件的數組。 –

+0

@Aleksei Vasiliev在1完成前得到線程轉儲可能很有用 –

回答

0

你會得到線程捱餓。您需要爲Java進行睡眠或IO才能正確管理線程。它不是JVM的故障操作系統線程被破壞了。

相關問題