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
下面是完整的代码:
明白产生死锁的原因后,就要如何快速清除缓存,我们一般的做法是先读取完标准输出流然后再读取错误输出流,这样就容易造成进程阻塞,而网上很多文章是使用两个线程,同时处理标准输出流和错误输出流,感觉上好像不错,但是代码写得不太酷,其实造成进程阻塞的原因不应该是我们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(); } } } }
相关文章推荐
- Process 缓存区死锁
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- java中死锁,并发,web缓存的相关问题
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- Process的Waitfor() 引起代码死锁
- IntelliJ IDEA修改Output输出缓存区大小【应对:too much output to process】
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- C# Process.WaitForExit()与死锁
- PRB: Process.waitFor() 进入一个死锁时父进程不会读取子进程数据
- mysql kill process解决死锁
- nginx - cache manage process 过期缓存定期清理的实现
- C# Process.WaitForExit()与死锁
- 使用GetProcessHeaps()和HeapValidate()函数定位缓存溢出
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- C#执行ADD命令是Process.WaitForExit()出现死锁
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- Android知识点:process属性、openOrCreateDatabase、URLEncoder.encode、垃圾回收、 缓存处理、断点续传 推荐
- Notes: Process in Operation System and Dead Lock 操作系统中的进程和死锁问题
- Python subprocess 死锁