隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網站

          關注的網站

          協議

          喜歡的Blog

          國內廣告平臺

          圖書出版

          在線培訓

          開發工具

          微博客戶端

          手機鈴聲

          操作系統

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統

          數學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1974635
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          Java的多進程運行模式分析

          本文為原創,如需轉載,請注明作者和出處,謝謝!

          本文曾發表于天極網:http://dev.yesky.com/284/2659284.shtml

              一般我們在java中運行其它類中的方法時,無論是靜態調用,還是動態調用,都是在當前的進程中執行的,也就是說,只有一個java虛擬機實例在運行。而有的時候,我們需要通過java代碼啟動多個java子進程。這樣做雖然占用了一些系統資源,但會使程序更加穩定,因為新啟動的程序是在不同的虛擬機進程中運行的,如果有一個進程發生異常,并不影響其它的子進程。

          在Java中我們可以使用兩種方法來實現這種要求。最簡單的方法就是通過Runtime中的exec方法執行java classname。如果執行成功,這個方法返回一個Process對象,如果執行失敗,將拋出一個IOException錯誤。下面讓我們來看一個簡單的例子。

          // Test1.java文件
          import java.io.*;
          public class Test
          {
          public static void main(String[] args)
          {
          FileOutputStream fOut 
          = new FileOutputStream("c:\\Test1.txt");
          fOut.close();
          System.out.println(
          "被調用成功!");
          }
          }

          // Test_Exec.java
          public class Test_Exec
          {
          public static void main(String[] args)
          {
          Runtime run 
          = Runtime.getRuntime();
          Process p 
          = run.exec("java test1");
          }
          }

          通過java Test_Exec運行程序后,發現在C盤多了個Test1.txt文件,但在控制臺中并未出現"被調用成功!"的輸出信息。因此可以斷定,Test已經被執行成功,但因為某種原因,Test的輸出信息未在Test_Exec的控制臺中輸出。這個原因也很簡單,因為使用exec建立的是Test_Exec 的子進程,這個子進程并沒有自己的控制臺,因此,它并不會輸出任何信息。

          如果要輸出子進程的輸出信息,可以通過Process中的getInputStream得到子進程的輸出流(在子進程中輸出,在父進程中就是輸入),然后將子進程中的輸出流從父進程的控制臺輸出。具體的實現代碼如下如示:

          // Test_Exec_Out.java
          import java.io.*;
          public class Test_Exec_Out
          {
          public static void main(String[] args)
          {
          Runtime run 
          = Runtime.getRuntime();
          Process p 
          = run.exec("java test1");
          BufferedInputStream in 
          = new BufferedInputStream(p.getInputStream());
          BufferedReader br 
          = new BufferedReader(new InputStreamReader(in));
          String s;
          while ((s = br.readLine()) != null)
          System.out.println(s);
          }
          }


          從上面的代碼可以看出,在Test_Exec_Out.java中通過按行讀取子進程的輸出信息,然后在Test_Exec_Out中按每行進行輸出。上面討論的是如何得到子進程的輸出信息。那么,除了輸出信息,還有輸入信息。既然子進程沒有自己的控制臺,那么輸入信息也得由父進程提供。我們可以通過 Process的getOutputStream方法來為子進程提供輸入信息(即由父進程向子進程輸入信息,而不是由控制臺輸入信息)。我們可以看看如下的代碼:

          // Test2.java文件
          import java.io.*;
          public class Test
          {
          public static void main(String[] args)
          {
          BufferedReader br 
          = new BufferedReader(new InputStreamReader(System.in));
          System.out.println(
          "由父進程輸入的信息:" + br.readLine());
          }
          }

          // Test_Exec_In.java
          import java.io.*;
          public class Test_Exec_In
          {
          public static void main(String[] args)
          {
          Runtime run 
          = Runtime.getRuntime();
          Process p 
          = run.exec("java test2");
          BufferedWriter bw 
          = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
          bw.write(
          "向子進程輸出信息");
          bw.flush();
          bw.close(); 
          // 必須得關閉流,否則無法向子進程中輸入信息
          // System.in.read();
           }
          }

          從以上代碼可以看出,Test1得到由Test_Exec_In發過來的信息,并將其輸出。當你不加bw.flash()和bw.close()時,信息將無法到達子進程,也就是說子進程進入阻塞狀態,但由于父進程已經退出了,因此,子進程也跟著退出了。如果要證明這一點,可以在最后加上 System.in.read(),然后通過任務管理器(在windows下)查看java進程,你會發現如果加上bw.flush()和 bw.close(),只有一個java進程存在,如果去掉它們,就有兩個java進程存在。這是因為,如果將信息傳給Test2,在得到信息后, Test2就退出了。在這里有一點需要說明一下,exec的執行是異步的,并不會因為執行的某個程序阻塞而停止執行下面的代碼。因此,可以在運行 test2后,仍可以執行下面的代碼。
          exec方法經過了多次的重載。上面使用的只是它的一種重載。它還可以將命令和參數分開,如exec("java.test2")可以寫成exec("java", "test2")。exec還可以通過指定的環境變量運行不同配置的java虛擬機。

          除了使用Runtime的exec方法建立子進程外,還可以通過ProcessBuilder建立子進程。ProcessBuilder的使用方法如下:

          // Test_Exec_Out.java
          import java.io.*;
          public class Test_Exec_Out
          {
          public static void main(String[] args)
          {
          ProcessBuilder pb 
          = new ProcessBuilder("java""test1");
          Process p 
          = pb.start();
          … …
          }
          }

          在建立子進程上,ProcessBuilder和Runtime類似,不同的ProcessBuilder使用start()方法啟動子進程,而Runtime使用exec方法啟動子進程。得到Process后,它們的操作就完全一樣的。

          ProcessBuilder和Runtime一樣,也可設置可執行文件的環境信息、工作目錄等。下面的例子描述了如何使用ProcessBuilder設置這些信息。

          ProcessBuilder pb = new ProcessBuilder("Command""arg2""arg2"''');
          // 設置環境變量
          Map<String, String> env = pb.environment();
          env.put(
          "key1""value1");
          env.remove(
          "key2");
          env.put(
          "key2", env.get("key1"+ "_test");
          pb.directory(
          "..\abcd"); // 設置工作目錄
          Process p = pb.start(); // 建立子進程




          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-05-10 19:02 銀河使者 閱讀(2983) 評論(1)  編輯  收藏 所屬分類: java 原創

          評論

          # re: Java的多進程運行模式分析[未登錄]  回復  更多評論   

          學習 http://www.dwww.cn
          2009-06-19 21:15 | hello java
          主站蜘蛛池模板: 常宁市| 长治市| 镇原县| 荔浦县| 丹江口市| 民乐县| 灵石县| 丰顺县| 隆尧县| 梅州市| 河西区| 东宁县| 庆安县| 富民县| 凤冈县| 武山县| 高碑店市| 武城县| 通化县| 洪泽县| 东辽县| 定襄县| 连南| 湾仔区| 油尖旺区| 苗栗市| 剑河县| 伊春市| 前郭尔| 临高县| 彭泽县| 碌曲县| 婺源县| 高雄市| 阿城市| 六枝特区| 云和县| 丹巴县| 新宾| 江城| 保亭|