运行批处理文件时Java程序挂起

时间:2018-12-04 11:16:51

标签: java multithreading batch-file concurrency

我正在使用下面的代码从输入数据生成报告。当只有少量数据时,以下代码可以正常工作。但是,当数据量变大时,我的程序挂起,必须使用任务管理器关闭该应用程序才能终止该进程。

public void launchReport() {

    if( selectionRulesRespected ) {

        final Process p;

        final String userNameParLine = getUserNameParLine();
        final String injParLine = getFilterByFieldParLine();

        writeTmpParFile(tmpParFilePath, new String[]{userNameParLine, injParLine});

        try {
            final ProcessBuilder builder;
            if( exporting != null && "TRUE".equals(exporting.toUpperCase()) ) {
                builder = new ProcessBuilder("cmd", "/c", batFilePath, reportName, tmpParFilePath, exportFilePath);
            }
            else {
                builder = new ProcessBuilder("cmd", "/c", batFilePath, reportName, tmpParFilePath);
            }
            //builder.directory( new File(viewerDirPath));
            p = builder.start();
            p.waitFor();
        } catch (final IOException e) {
            PlanonMessageDialog.showErrorDialog(ioError);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }

    } else {
        PlanonMessageDialog.showErrorDialog(wrongItem);
    }
}

应用程序挂起,因为此方法等待进程完成。我可以使用哪些选项?

1 个答案:

答案 0 :(得分:0)

您的 java 代码使用 p.waitFor() 等待进程终止。但是该进程写入 stdout/stderr,缓冲区已满,因此 Windows 阻止它进一步执行 - 相反,它等待缓冲区被清空。两个进程互相等待——这是一个典型的死锁。

为了防止这种情况,将 p.waitFor() 替换为检查进程是否已退出的循环。如果不是,则从 stdout 和 stderr 读取。

另见https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Process.html