[Java][Android][Process] ProcessBuilder與Runtime區別
阿新 • • 發佈:2019-01-24
在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個已經建立的程序,而外部的執行緒重複利用以及建立的程序,不知這樣是否可行?
望大家探討一下解決方法,謝謝了。