您的位置:首页 > 其它

Process 缓存区死锁

2014-12-15 20:57 106 查看
在开发的过程中,有时候会使用JAVA Runtime.exec() 方式运行某条命令或脚本,而在很大的情况下会出现 Process 缓存区死锁,为什么会出现死锁。JDK 开发文档说得很清楚:有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。

明白产生死锁的原因后,就要如何快速清除缓存,我们一般的做法是先读取完标准输出流然后再读取错误输出流,这样就容易造成进程阻塞,而网上很多文章是使用两个线程,同时处理标准输出流和错误输出流,感觉上好像不错,但是代码写得不太酷,其实造成进程阻塞的原因不应该是我们JAVA要处理的,所以我们应该交给要运行的脚本或者命令处理。

这里以执行windows CMD为例子。

CMD有多个输出,如STDOUT 和 STDERR,对应的是getInputStream() 和 getErrorStream(),而我们要做的是把错误输出和标准输出合并即可,在CMD命令中可以使用“2>&1”使错误输出重定向标准输出,这样就可以代码中直接使用getInputStream()而不用使用getErrorStream(),避免Process 缓冲区死锁。例如,CMD命令

cmd.exe /E:NO /c %s 2>&1

关于CMD重定向的内容,请移步到 http://www.cnblogs.com/xiongjiaji/articles/2445539.html

下面是完整的代码:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Cmd {

private static final String TAG = Cmd.class.getSimpleName();

private static final String CODE_TYPE = "UTF-8";

private static final String COMMAND = "cmd.exe /E:NO /c %s 2>&1";

public static String executeCmd(String cmd) {

StringBuilder stringBuilder = new StringBuilder();
BufferedInputStream input = null;
ByteArrayOutputStream outputStream = null;
Process pro = null;
try {

outputStream = new ByteArrayOutputStream();
byte[] data = new byte[4 * 1024];
int index = -1;

String cmdStr = String.format(COMMAND, cmd);
pro = Runtime.getRuntime().exec(cmdStr);
input = new BufferedInputStream(pro.getInputStream());

while ((index = input.read(data)) != -1) {
outputStream.write(data, 0, index);
}

byte[] msgData = outputStream.toByteArray();
if (msgData != null) {
String msg = new String(msgData, CODE_TYPE);
stringBuilder.append(msg);
}

} catch (Exception e) {
e.printStackTrace();
//			Log.v(TAG, "executeCmd error");
} finally {
closeOutPutStream(outputStream);
closeInputStream(input);
closeProcess(pro);
}

return stringBuilder.toString();

}

private static void closeProcess(Process pro) {
if (pro != null) {

try {
if (pro.exitValue() == 0) {
pro.destroy();
}
} catch (Exception e) {
e.printStackTrace();
}

}
}

private static void closeInputStream(InputStream inputStream) {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

private static void closeOutPutStream(OutputStream outputStream) {
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: