0

我有以下代码运行一个进程,我想知道运行它时是否有异常。它无缘无故挂起

Runtime runtime = Runtime.getRuntime();
proc = runtime.exec(command.toString());
ProcessHandler errorStream = new ProcessHandler(proc.getErrorStream(),"ERROR", rdyFilePath);
ExecutorService pool = Executors.newSingleThreadExecutor();
Future future = pool.submit(errorStream);
pool.shutdown();

try {
     if(future.get() == null) {
         log.info("Done completing error thread");
     }
} catch (InterruptedException | ExecutionException e) {
     e.printStackTrace();
}

这是进程处理程序的类

public class ProcessHandler implements Callable<Integer> {

    private static Logger log = Logger.getLogger(ProcessHandler.class.getName());

    InputStream inpStr;
    String strType;
    String rdyFile;


    public ProcessHandler(InputStream inpStr, String strType, String rdyFile) {
        this.inpStr = inpStr;
        this.strType = strType;
        this.rdyFile = rdyFile;
    }

    public Integer call() throws FileMetadataException {
        StringBuffer sb = new StringBuffer();
        try {

            InputStreamReader inpStrd = new InputStreamReader(inpStr);
            BufferedReader buffRd = new BufferedReader(inpStrd);
            String line = null;
            while((line = buffRd.readLine()) != null) {
                if("ERROR".equalsIgnoreCase(strType)) {

                    sb.append(line + "\n");
                    log.info(strType + "->" + line);
                }
            }
            if(sb != null) {
                log.info("Error Stream length : " + sb.length());
                throw new RuntimeException();

            }

            buffRd.close();
        } catch(IOException e) {
            log.error("IOException in ProcessHandler Thread" + e.fillInStackTrace());
            System.err.println(e);
            throw new FileMetadataException();
        } finally {
            if(sb != null) {
                if(sb.toString().length() > 0 ) {
                    log.error("Error string buffer length " + sb.length());
                    // do not create rdy file
                } else {
                    log.error("Error string buffer length : " + sb.length());
                    File f = new File(rdyFile);
                        try {
                            f.createNewFile();
                        } catch(IOException e) {
                            log.error("IOException while creating rdy file");
                        }
                    }
                    // create rdy file. 
                }
            }
            return sb.length();
        }

    }
}
4

2 回答 2

2

Processjavadoc:

由于部分原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。

根据此警告,您的future.get()方法已挂起,因为您仅使用来自流程对象的错误流。在我曾经使用过Process对象的所有平台上,我观察到您需要同时使用错误和标准输出流。

是一个很好的工具,它使用多线程方法来确保进程的流被消耗。

在这种情况下,由于您似乎不关心流程的标准输出,您可以添加类似这样的内容,借用StreamHelper类:

StreamHelper inStreamHelper = new StreamHelper(proc.getInputStream());
inStreamHelper.start();
于 2013-09-17T22:24:20.920 回答
2

我有以下代码运行一个进程,我想知道运行它时是否有异常。它无缘无故挂起

如果有一个异常,你future.get()应该抛出一个ExecutionException-- 它不会“挂起”。您确定您的异常没有被打印,而是在日志或控制台输出中以某种方式丢失了吗?

在跟踪您的代码时,我认为您的程序在完成读取流后无法完成。也许您正在读取其错误流的进程仍在运行并且InputStream尚未关闭?也许有这么多的输出,你正在用StringBuffer(应该改为StringBuilderbtw)填充核心。

您可以使用 jconsole 附加到您的应用程序以查看线程是否仍在运行,如果是,它在做什么?

 if(future.get() == null) {
     log.info("Done completing error thread");
 }

null因此,如果您从您的call()方法返回,这只会记录输出。这永远不会发生,因为唯一的回报是return sb.length();. 所以要么你会从你的异常中得到一个异常,call()要么你的结果将是一个非 null Integer

于 2013-09-17T20:22:40.567 回答