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可能更合適。
文件變量的定義是什麼?它是完整的50個文件嗎? –
files變量是一個包含全部50個輸入PNG文件的數組。 –
@Aleksei Vasiliev在1完成前得到線程轉儲可能很有用 –