在做视频转换时,调用外部的 exe 去进行一些视频转换的操作时,因为考虑到速度问题,当时是通过启动多个线程来共同完成某个操作的,因为是多线程操作,所以当时我控制的主线程等待所有子线程执行完后再继续向下去执行。但是始终出现发现没有控制住子线程未执行完主线程就向下继续执行的情况,开始因为是启动多线程时线程控制问题,后来发现是子线程中利用 Process 调用外部 exe 时出现了 waitFor() 方法阻塞问题(唉,折腾啊)。 Ok ,知道问题就好解决了。
首先来解释一下 waitFor() 方法的意义, waitFor() 表示当前 Process 所在的子线程处于等待状态,如有必要,一直要等到由该 Process 对象表示的进程已经终止,网上说如果我们在调用此方法时,如果不注意的话,很容易出现主线程阻塞, Process 也挂起的情况。这就是我遇到的问题,网上的解决办法是,在调用 waitFor() 的时候, Process 需要向主线程汇报运行状况,所以要注意清空缓存区,即 InputStream 和 ErrorStream ,注意这里 InputStream 和 ErrorStream 都需要清空。
package com.iflytek.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
*
* @author xdwang
*
* @ceate 2012-7-20 下午22:52:25
*
* @email xdwangiflytek@gmail.com
*
* @description 清除process里的InputStream和ErrorStream 缓存
*
*/
public class ProcessClearStream extends Thread {
private InputStream inputStream;
private String type;
ProcessClearStream(InputStream inputStream, String type) {
this.inputStream = inputStream;
this.type = type;
}
public void run() {
try {
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream);
BufferedReader br = new BufferedReader(inputStreamReader);
// 打印信息
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(type + ">" + line);
}
// 不打印信息
// while (br.readLine() != null);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
此时,我们再看看 Process 调用 exe 的方法:
package com.iflytek.util;
/**
* @author xdwang
*
* @ceate 2012-7-20 下午22:22:44
*
* @email xdwangiflytek@gmail.com
*
* @description process工具类
*
*/
public class ProcessUtil {
/**
* @descrption 执行外部exe公用方法
* @author xdwang
* @create 2012-7-20下午22:24:32
* @param cmdStr
* 命令字符串
*/
public static void execProcess(String cmdStr) {
Process process = null;
try {
System.out.println(cmdStr);
process = Runtime.getRuntime().exec(cmdStr);
new ProcessClearStream(process.getInputStream(), "INFO").start();
new ProcessClearStream(process.getErrorStream(), "ERROR").start();
int status = process.waitFor();
System.out.println("Process exitValue: " + status);
} catch (Exception e) {
System.out.println("执行" + cmdStr + "出现错误," + e.toString());
} finally {
if (process == null) {
process.destroy();
}
process = null;
}
}
}