我正在通过生成5个pngout.exe进程来优化PNG文件,以处理PNG文件的目录。由于pngout是单线程的,因此导致了很大的加速。一些图像需要很长时间来优化,超过30秒,而标准是<5秒。问题是:
代码:
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%的改进。
我做错了什么?
编辑:修复了这个问题,使用了一些非常难看的代码。问题是,为了获得我生成的进程的退出值(知道它们何时完成,以及它们是否成功),我没有读取它们的标准输出,因为调用waitFor将永远挂起。但是,显然使用InputStreams会使线程阻塞。
因此,要获得进程的退出值,而不是使用以下方法:
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个进程在运行。
后期编辑:来自这里的这里可能更合适。
发布于 2011-07-13 15:42:33
你要饿死了。您需要为java做一个睡眠或IO来正确地管理线程。这不是JVM的错误操作系统线程被破坏了。
https://stackoverflow.com/questions/6566630
复制相似问题