http://233.io/article/1000704.html
Android ProcessBuilder與Runtime.getRuntime().exec分别建立程序的差別
在Android中想要進行Ping,在不Root機器的情況下似乎還隻能進行底層命調用才能實作。
因為在Java中要進行ICMP包發送需要Root權限。
于是隻能通過建立程序來解決了,建立程序在Java中有兩種方式,分别為:
1. 調用ProcessBuilder的構造函數後執行start()
2. 用Runtime.getRuntime().exec()方法執行
經過使用後發現兩者有差別但是也并不是很大,兩個例子說明:
1.調用ProcessBuilder的構造函數後執行start():
Process process = new ProcessBuilder("/system/bin/ping").redirectErrorStream(true).start();
OutputStream stdout = process.getOutputStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));
2.用Runtime.getRuntime().exec()方法執行:
Process process = Runtime.getRuntime().exec("/system/bin/ping");
OutputStream stdout = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedReader err= new BufferedReader(new InputStreamReader(stderr));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));
兩者在執行效率上沒啥差別,可能是我沒有發現。兩種測試的差別在于是否可以重定向錯誤流。
使用ProcessBuilder,可以通過redirectErrorStream(true)将錯誤輸出流轉移到标準輸出流中,這樣使用一次process.getInputStreamReader()就能讀出該程序的所有輸出。
而使用Runtime.getRuntime().exec()方法時,錯誤的輸出流還需通過process.getErrorStream()來獲得。
分享一個自己集合的一個程序執行後銷毀的類:
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessModel {
/**
* 通過Android底層實作程序關閉
*
* @param process
*/
public static void killProcess(Process process) {
int pid = getProcessId(process.toString());
if (pid != 0) {
try {
android.os.Process.killProcess(pid);
} catch (Exception e) {
try {
process.destroy();
} catch (Exception ex) {
}
}
}
}
/**
* 擷取目前程序的ID
*
* @param str
* @return
*/
public static int getProcessId(String str) {
try {
int i = str.indexOf("=") + 1;
int j = str.indexOf("]");
String cStr = str.substring(i, j).trim();
return Integer.parseInt(cStr);
} catch (Exception e) {
return 0;
}
}
/**
* 關閉程序的所有流
*
* @param process
*/
public static void closeAllStream(Process process) {
try {
InputStream in = process.getInputStream();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
InputStream in = process.getErrorStream();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
OutputStream out = process.getOutputStream();
if (out != null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 銷毀一個程序
*
* @param process
*/
public static void processDestroy(Process process) {
if (process != null) {
try {
if (process.exitValue() != 0) {
closeAllStream(process);
killProcess(process);
}
} catch (IllegalThreadStateException e) {
closeAllStream(process);
killProcess(process);
}
}
}
/**
* 通過線程進行異步銷毀
*
* @param process
*/
public static void asyncProcessDestroy(final Process process) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
processDestroy(process);
}
});
thread.setDaemon(true);
thread.start();
}
}
奇怪的是,當使用線程進行大量的程序建立,最後達到一定數量(大約為1000個左右)的時候将會出現無法建立程序的情況;
此情況我不知怎麼解決,自己想的是弄一個線程池裡邊放20個已經建立的程序,而外部的線程重複利用以及建立的程序,不知這樣是否可行?