1、判斷子進程是否執行結束
有的時候我們用java調用shell之後,之後的操作要在Process子進程正常執行結束的情況下才可以繼續,所以我們需要判斷Process進程什麼時候終止。
Process類提供了waitFor()方法。該方法導致當前線程等待,直到Process線程終止。
Process.waitFor()是有一個int類型返回值的,當返回值為0的時候表Process進程正常終止。否則一般是腳本執行出錯了(我遇到的一般是這種情況)。
2、Process.waitFor()導致當前線程阻塞。
有的時候我們發現調用waitFor()方法後,java主線程會一直阻塞在waitFor()處,阻塞的原因是什麼呢?分析一下:
Java在執行Runtime.getRuntime().exec(jyName)之後,Linux會創建一個進程,該進程與JVM進程建立三個管道連接,標准輸入流、標准輸出流、標准錯誤流,假設linux進程不斷
向標准輸出流和標准錯誤流寫數據,而JVM卻不讀取,數據會暫存在linux緩存區,當緩存區存滿之後導致該進程無法繼續寫數據,會僵死,導致java進程會卡死在waitFor()處,
永遠無法結束。
解決辦法:java進程在waitFor()前不斷讀取標准輸出流和標准錯誤流:
//jyName 解壓腳本路徑
String fileName=fileList.get(0).toString().substring(fileList.get(0).toString().lastIndexOf(File.separator)+1);
String jyName="/etc/zxvf.sh "+fileName;
try {
Process p0 = Runtime.getRuntime().exec(jyName);
//讀取標准輸出流
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(p0.getInputStream()));
String line;
while ((line=bufferedReader.readLine()) != null) {
System.out.println(line);
}
//讀取標准錯誤流
BufferedReader brError = new BufferedReader(new InputStreamReader(p0.getErrorStream(), "gb2312"));
String errline = null;
while ((errline = brError.readLine()) != null) {
System.out.println(errline);
}
//waitFor()判斷Process進程是否終止,通過返回值判斷是否正常終止。0代表正常終止
int c=p0.waitFor();
if(c!=0){
baseRes.put("desc", "軟件升級失敗:執行zxvf.sh異常終止");
baseRes.setReturnFlag(false);
return baseRes;
}
} catch (IOException e1) {
baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
baseRes.setReturnFlag(false);
return baseRes;
} catch (InterruptedException e1) {
baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
baseRes.setReturnFlag(false);
return baseRes;
}
也可以在執行Runtime.getRuntime().exec(jyName)之後另外再啟動兩個線程分別讀取標准錯誤流和標准輸出流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ExcuteThread extends Thread {
private String name;
public ExcuteThread(String name) {
this.name = name;
}
@Override
public void run() {
try {
Process p = Runtime.getRuntime().exec(name);
InputStream fis = p.getInputStream();
final BufferedReader brError = new BufferedReader(
new InputStreamReader(p.getErrorStream(), "gb2312"));
InputStreamReader isr = new InputStreamReader(fis, "gb2312");
final BufferedReader br = new BufferedReader(isr);
Thread t1 = new Thread() {
public void run() {
String line = null;
try {
while ((line = brError.readLine()) != null) {
// System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (brError != null)
brError.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
String line = null;
try {
while ((line = br.readLine()) != null) {
// System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
t1.start();
t2.start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
}
}
}