【问题标题】:Processes don't terminate进程不会终止
【发布时间】:2016-04-16 11:17:27
【问题描述】:

我正在使用 Java Executors.newWorkStealingPool(); 并行运行多个命令。由于其中一些任务预计会超时,因此我为它们添加了 2 秒的超时时间。

ProcessBuilder pb = new ProcessBuilder(cmd.split(" "));
Process p = null;
StringBuilder result = new StringBuilder();
try {
    p = pb.start();
    p.waitFor(2000, TimeUnit.MILLISECONDS);
    BufferedReader errreader = 
    new BufferedReader(new InputStreamReader(p.getErrorStream()));
    BufferedReader outreader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = "";           
    while ((line = outreader.readLine())!= null) 
    result.append(line + "\n");
    while ((line = errreader.readLine())!= null) 
        result.append(line + "\n");
    outreader.close();
    errreader.close();
    } catch (InterruptedException e) {
        result.append("INTERRUPTED");
    } catch (IOException e) {
        e.printStackTrace();
        System.exit(-1);
    }
    finally {
        p.destroy();
    }
    ....
    return b; // b is boolean

提交任务是这样的

List<ImmutablePair> curJobs = new ArrayList<ImmutablePair>();
for (int i = 0; i <  allMutants.size(); i++) {
    String mutant = allMutants.get(i);
    t = executor.submit(new mutTask(mutant));
    ImmutablePair pair = new ImmutablePair(mutant, t);
    curJobs.add(pair);
    }

最后。我在以下循环中收集结果。

// data collection loop
for (int i = 0; i< curJobs.size(); i++) {
        ImmutablePair p = curJobs.get(i);
        String m= (String) p.getLeft();
    System.out.println(m);
        t = (Future<Boolean>) p.getRight();
    try {
        boolean res;
        try {
            res = t.get(2000L, TimeUnit.MILLISECONDS);

        } catch (TimeoutException e) {
            res = true;
        }
        finally {
            t.cancel(true);
        }}

问题在于,超时似乎并没有像程序中定义的那样终止某些命令或进程。几分钟后,数据收集循环变得非常缓慢。 ps 的结果显示一些作业在指定的超时时间以上运行并保持 CPU 繁忙。我的配置是 CentOS 上的 JDK8。

【问题讨论】:

  • 所以,从JavaDocs中,我们知道“如果需要,使当前线程等待,直到这个Process对象所代表的子进程已经终止,或者指定的等待时间过去了。”,这意味着该方法将在进程存在或指定时间过去时返回,因此这意味着该进程可能仍在运行。接下来,您然后读取进程输出的内容,这意味着,如果进程仍在破坏,它要么仍在处理输出,要么正在阻塞...通常我使用子 Thread 来读取输入,当 @987654327 @return,停止这些线程
  • ...然后销毁进程
  • 谢谢。正如您所指出的,问题不是检查p.waitFor(2000, TimeUnit.MILLISECONDS); 的输出。

标签: java concurrency process command java.util.concurrent


【解决方案1】:

正如@MadProgrammer 指出的那样,问题是在进程终止的情况下读取/错误缓冲区。要解决这个问题,您需要检查p.waitFor(2000, TimeUnit.MILLISECONDS);的输出

    try {
        p = pb.start();
        boolean timeout = !p.waitFor(2000, TimeUnit.MILLISECONDS);
        if (!timeout){
            BufferedReader errreader =
                     new BufferedReader(new InputStreamReader(p.getErrorStream()));
            BufferedReader outreader =
                     new BufferedReader(new InputStreamReader(p.getInputStream()));

            String line = "";
            while ((line = outreader.readLine())!= null)
                result.append(line + "\n");
            while ((line = errreader.readLine())!= null)
                    result.append(line + "\n");
            outreader.close();
            errreader.close();
        }

    } catch ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    相关资源
    最近更新 更多