java runtime exec 运行挂起的问题
2011-11-24 10:51
309 查看
这两天让一个同事去做一个ORACLE数据定时备份的工作,结果她写完代码后发现可以导出备份文件,但是使用RUNTIME的时候没办法结束,也就是说这个进程一直处于挂起的状态,是什么原因呢?
为了解决这个问题到网上找了下,有这么一段英文资料:
The next version of Savant is going to focus heavily on the stand-alone runtime and support for dialects and plugins. Supporting all that is largely handled by using a simple executor framework I wrote around Java 1.4 and lower’s Runtime.exec method. A few
things to keep in mind when using this:
Always read from the streams prior to calling waitFor. Otherwise you could end up waiting forever on Windows and other OS platforms whose I/O buffers can’t store enough from standard out and standard error to ensure the program has finished. These platforms
will pause the execution of whatever is running until something reads the buffered content from standard out and standard error. I would imagine all platforms suffer from this, but some platforms have larger buffers than others. Needless to say, always read
from the streams first.
Always read from standard error first. I ran across a bug where some OS platforms will always open standard out, but never close it. What this means is that if you read from standard out first and the process only writes to standard error, you’ll hang forever
waiting to read. If you read from standard error first, you’ll always be okay on these platforms because the OS seems to shutdown standard error. I think however, that the best way to handle all cases is to check both standard error and standard out for readiness
and only read from them if they have something to offer. The downside I could see here is that error isn’t ready, but eventually will be.
可以看出来:
1.要在调用waitFor()方法之前读取数据流
2.要先从标准错误流中读取,然后再读取标准输出流,因为runtime默认先读取错误流,一旦错误流没被读取,这个进程就回被挂起
找到了原因,那么可以使用如下的解决方法:
测试类如下:
解决挂起的多线程类如下:
当然后来经过同事的提醒,发现不开辟一个新的线程处理错误流,也可以
代码如下:
有人肯定会问了,那么开辟线程处理错误流和不开辟线程处理错误流有什么区别呢?
在此我做了个实验,对这两种解决挂起的方法做了运行效率的比较,发现使用多线程处理数据流的效率要略高于单线程处理,即多线程使用的时间比不使用要少!
为了解决这个问题到网上找了下,有这么一段英文资料:
The next version of Savant is going to focus heavily on the stand-alone runtime and support for dialects and plugins. Supporting all that is largely handled by using a simple executor framework I wrote around Java 1.4 and lower’s Runtime.exec method. A few
things to keep in mind when using this:
Always read from the streams prior to calling waitFor. Otherwise you could end up waiting forever on Windows and other OS platforms whose I/O buffers can’t store enough from standard out and standard error to ensure the program has finished. These platforms
will pause the execution of whatever is running until something reads the buffered content from standard out and standard error. I would imagine all platforms suffer from this, but some platforms have larger buffers than others. Needless to say, always read
from the streams first.
Always read from standard error first. I ran across a bug where some OS platforms will always open standard out, but never close it. What this means is that if you read from standard out first and the process only writes to standard error, you’ll hang forever
waiting to read. If you read from standard error first, you’ll always be okay on these platforms because the OS seems to shutdown standard error. I think however, that the best way to handle all cases is to check both standard error and standard out for readiness
and only read from them if they have something to offer. The downside I could see here is that error isn’t ready, but eventually will be.
可以看出来:
1.要在调用waitFor()方法之前读取数据流
2.要先从标准错误流中读取,然后再读取标准输出流,因为runtime默认先读取错误流,一旦错误流没被读取,这个进程就回被挂起
找到了原因,那么可以使用如下的解决方法:
测试类如下:
public class TESTRuntime { public String cmdexeStr = "exp test/test file=d:/daochu.dmp tables=(t_test)"; public String startRunTime(){ try { Process proc = Runtime.getRuntime().exec(cmdexeStr); ProcessStreamUtil errorProcStream = new ProcessStreamUtil(proc.getErrorStream(),"Error"); ProcessStreamUtil outputProcStream = new ProcessStreamUtil(proc.getInputStream(),"Output"); errorProcStream.start(); outputProcStream.start(); int num = proc.waitFor(); System.out.println("------num:"+num); proc.destroy(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void main(String[] args) { System.out.println("------------start run--------------"); TESTRuntime test = new TESTRuntime(); test.startRunTime(); System.out.println("------------end run--------------"); } }
解决挂起的多线程类如下:
public class ProcessStreamUtil extends Thread{ private InputStream inputStream; private String type; private int i=0; public ProcessStreamUtil(InputStream inputStream,String type){ this.inputStream = inputStream; this.type = type; } public void run() { System.out.println("------type:"+type+"--------start--------------"); try { i = i+1; InputStreamReader isr = new InputStreamReader(inputStream); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { if (type.equals("Error")){ System.out.println("------i:"+i+"-------error:\n"+line); }else{ System.out.println("------i:"+i+"--------debug:\n"+line); } } } catch (IOException ioe) { ioe.printStackTrace(); } System.out.println("------type:"+type+"--------end--------------"); } public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
当然后来经过同事的提醒,发现不开辟一个新的线程处理错误流,也可以
代码如下:
public class TESTRuntime { public String cmdexeStr = "exp test/test file=d:/daochu.dmp tables=(t_test)"; public String startRunTime(){ try { Process proc = Runtime.getRuntime().exec(cmdexeStr); InputStream errorProcStream = proc.getErrorStream(); InputStream outputProcStream = proc.getInputStream(); InputStreamReader errorRead = new InputStreamReader(errorProcStream); InputStreamReader outputRead = new InputStreamReader(outputProcStream); BufferedReader errorbr = new BufferedReader(errorRead); String errorline = null; while ((errorline = errorbr.readLine()) != null) { System.out.println("------error:/n"+errorline); } BufferedReader outputbr = new BufferedReader(outputRead); String outputline = null; while ((outputline = outputbr.readLine()) != null) { System.out.println("------debug:/n"+outputline); } int num = proc.waitFor(); System.out.println("------num:"+num); proc.destroy(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void main(String[] args) { System.out.println("------------start run--------------"); TESTRuntime test = new TESTRuntime(); test.startRunTime(); System.out.println("------------end run--------------"); } }
有人肯定会问了,那么开辟线程处理错误流和不开辟线程处理错误流有什么区别呢?
在此我做了个实验,对这两种解决挂起的方法做了运行效率的比较,发现使用多线程处理数据流的效率要略高于单线程处理,即多线程使用的时间比不使用要少!
相关文章推荐
- java runtime exec hang up 运行挂起的问题
- 64位xp上java Runtime.exec无法正常运行的问题
- Drools 运行时出现 java.lang.RuntimeException: wrong class format 问题解决
- 工作中遇到的关于java runtime.exec()的问题
- 工作中遇到的关于java runtime.exec()的问题
- [转]DroidDraw不能运行,显示The application requires a Java Runtime Environment 1.4.0的问题
- java的runtime.exec创建的线程被挂起的解决办法。
- java使用Runtime.exec执行linux命令重定向或管道问题
- 今天解决了Runtime.getRuntime().exec()运行的问题
- Java运行系统命令并获取值(Process java.lang.Runtime.exec(String[] cmdarray, String[] envp, File dir)
- [Java] 关于java.lang.Runtime.exec()方法运行命令所在目录的探讨。
- Java Process中waitFor()的问题(使用Runtime.getRuntime().exec(...)时)
- [JAVA]关于Runtime.exec的问题
- Drools 运行时出现Exception in thread "main" java.lang.RuntimeException: wrong class format 的问题
- Eclipse下使用Runtime.getRuntime().exec启动java程序的问题
- java调用命令行Runtime.getRuntime().exec()阻塞问题
- java使用Runtime.exec()运行windwos dos或linux shell命令
- ※※Java调用Runtime.exec()要注意的问题
- java Runtime.exec() 执行问题
- Java Runtime exec的挂掉问题,