首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >长时间的计算导致ExecutorService停止分配新的工作

长时间的计算导致ExecutorService停止分配新的工作
EN

Stack Overflow用户
提问于 2011-07-04 01:42:30
回答 1查看 295关注 0票数 4

我正在通过生成5个pngout.exe进程来优化PNG文件,以处理PNG文件的目录。由于pngout是单线程的,因此导致了很大的加速。一些图像需要很长时间来优化,超过30秒,而标准是<5秒。问题是:

  • 文件1是大的,2-5是小的,总共50个文件但是rest的细节无关.
  • 前五个pngout过程正常产卵并开始工作。
  • 2-5在10秒内离开
  • 1只需45秒
  • 在此过程中不会产生新的pngout进程,尽管有四个线程是空闲的。
  • 1完成后,将产生另外5个进程。

代码:

代码语言:javascript
复制
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会使线程阻塞。

因此,要获得进程的退出值,而不是使用以下方法:

代码语言:javascript
复制
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);
    }
}

我使用的是这个总代码:

代码语言:javascript
复制
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个进程在运行。

后期编辑:来自这里这里可能更合适。

EN

回答 1

Stack Overflow用户

发布于 2011-07-13 15:42:33

你要饿死了。您需要为java做一个睡眠或IO来正确地管理线程。这不是JVM的错误操作系统线程被破坏了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6566630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档