天天看點

[Java][Android][Process] ProcessBuilder與Runtime差別

在Android中想要進行Ping,在不Root機器的情況下似乎還隻能進行底層命調用才能實作。

因為在Java中要進行ICMP包發送需要Root權限。

于是隻能通過建立程序來解決了,建立程序在Java中有兩種方式,分别為:

1. 調用ProcessBuilder的構造函數後執行start()

2. 用Runtime.getRuntime().exec()方法執行

經過使用後發現兩者有差別但是也并不是很大,兩個例子說明:

1.調用ProcessBuilder的構造函數後執行start():

1. Process process = new ProcessBuilder("/system/bin/ping").redirectErrorStream(true).start();  
2. OutputStream stdout = process.getOutputStream();  
3. InputStream stdin = process.getInputStream();  
4. BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));  
5. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));      

2.用Runtime.getRuntime().exec()方法執行:

1. Process process = Runtime.getRuntime().exec("/system/bin/ping");  
2. OutputStream stdout = process.getOutputStream();  
3. InputStream stderr = process.getErrorStream();  
4. InputStream stdin = process.getInputStream();  
5. BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));  
6. BufferedReader err= new BufferedReader(new InputStreamReader(stderr));  
7. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));      

兩者在執行效率上沒啥差別,可能是我沒有發現。兩種測試的差別在于是否可以重定向錯誤流。

使用ProcessBuilder,可以通過redirectErrorStream(true)将錯誤輸出流轉移到标準輸出流中,這樣使用一次process.getInputStreamReader()就能讀出該程序的所有輸出。

而使用Runtime.getRuntime().exec()方法時,錯誤的輸出流還需通過process.getErrorStream()來獲得。

分享一個自己集合的一個程序執行後銷毀的類:

1. import java.io.InputStream;  
2. import java.io.OutputStream;  
3.   
4. public class ProcessModel {  
5.   
6. /**
7.      * 通過Android底層實作程序關閉
8.      *
9.      * @param process
10.      */  
11. public static void killProcess(Process process) {  
12. int pid = getProcessId(process.toString());  
13. if (pid != 0) {  
14. try {  
15.                 android.os.Process.killProcess(pid);  
16. catch (Exception e) {  
17. try {  
18.                     process.destroy();  
19. catch (Exception ex) {  
20.                 }  
21.             }  
22.         }  
23.     }  
24.   
25. /**
26.      * 擷取目前程序的ID
27.      *
28.      * @param str
29.      * @return
30.      */  
31. public static int getProcessId(String str) {  
32. try {  
33. int i = str.indexOf("=") + 1;  
34. int j = str.indexOf("]");  
35.             String cStr = str.substring(i, j).trim();  
36. return Integer.parseInt(cStr);  
37. catch (Exception e) {  
38. return 0;  
39.         }  
40.     }  
41.   
42.   
43. /**
44.      * 關閉程序的所有流
45.      *
46.      * @param process
47.      */  
48. public static void closeAllStream(Process process) {  
49. try {  
50.             InputStream in = process.getInputStream();  
51. if (in != null)  
52.                 in.close();  
53. catch (Exception e) {  
54.             e.printStackTrace();  
55.         }  
56. try {  
57.             InputStream in = process.getErrorStream();  
58. if (in != null)  
59.                 in.close();  
60. catch (Exception e) {  
61.             e.printStackTrace();  
62.         }  
63. try {  
64.             OutputStream out = process.getOutputStream();  
65. if (out != null)  
66.                 out.close();  
67. catch (Exception e) {  
68.             e.printStackTrace();  
69.         }  
70.     }  
71.   
72. /**
73.      * 銷毀一個程序
74.      *
75.      * @param process
76.      */  
77. public static void processDestroy(Process process) {  
78. if (process != null) {  
79. try {  
80. if (process.exitValue() != 0) {  
81.                     closeAllStream(process);  
82.                     killProcess(process);  
83.                 }  
84. catch (IllegalThreadStateException e) {  
85.                 closeAllStream(process);  
86.                 killProcess(process);  
87.             }  
88.         }  
89.     }  
90.   
91.   
92. /**
93.      * 通過線程進行異步銷毀
94.      *
95.      * @param process
96.      */  
97. public static void asyncProcessDestroy(final Process process) {  
98. new Thread(new Runnable() {  
99. @Override  
100. public void run() {  
101.                 processDestroy(process);  
102.             }  
103.         });  
104. true);  
105.         thread.start();  
106.     }  
107. }      

奇怪的是,當使用線程進行大量的程序建立,最後達到一定數量(大約為1000個左右)的時候将會出現無法建立程序的情況;

此情況我不知怎麼解決,自己想的是弄一個線程池裡邊放20個已經建立的程序,而外部的線程重複利用以及建立的程序,不知這樣是否可行?