程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java中多過程編程的完成

詳解Java中多過程編程的完成

編輯:關於JAVA

詳解Java中多過程編程的完成。本站提示廣大學習愛好者:(詳解Java中多過程編程的完成)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java中多過程編程的完成正文


1.Java過程的創立
Java供給了兩種辦法用來啟動過程或其它法式:
(1)應用Runtime的exec()辦法
(2)應用ProcessBuilder的start()辦法
1.1 ProcessBuilder 
   ProcessBuilder類是J2SE 1.5在java.lang中新添加的一個新類,此類用於創立操作體系過程,它供給一種啟動和治理過程(也就是運用法式)的辦法。在J2SE 1.5之前,都是由Process類處來完成過程的掌握治理。
每一個 ProcessBuilder 實例治理一個過程屬性集。start() 辦法應用這些屬性創立一個新的 Process 實例。start() 辦法可以從統一實例反復挪用,以應用雷同的或相干的屬性創立新的子過程。
每一個過程生成器治理這些過程屬性:
  敕令 是一個字符串列表,它表現要挪用的內部法式文件及其參數(假如有)。在此,表現有用的操作體系敕令的字符串列表是依附於體系的。例如,每個整體變量,平日都要成為此列表中的元素,但有一些操作體系,願望法式能本身標志敕令行字符串——在這類體系中,Java 完成能夠須要敕令確實地包括這兩個元素。
  情況 是從變量 到值 的依附於體系的映照。初始值是以後過程情況的一個正本(請參閱 System.getenv())。
任務目次。默許值是以後過程確當前任務目次,平日依據體系屬性 user.dir 來定名。
  redirectErrorStream 屬性。最後,此屬性為 false,意思是子過程的尺度輸入和毛病輸入被發送給兩個自力的流,這些流可以經由過程 Process.getInputStream() 和 Process.getErrorStream() 辦法來拜訪。假如將值設置為 true,尺度毛病將與尺度輸入歸並。這使得聯系關系毛病新聞和響應的輸入變得更輕易。在此情形下,歸並的數據可從 Process.getInputStream() 前往的流讀取,而從 Process.getErrorStream() 前往的流讀取將直接達到文件尾。
修正過程構建器的屬性將影響後續由該對象的 start() 辦法啟動的過程,但從不會影響之前啟動的過程或 Java 本身的過程。年夜多半毛病檢討由 start() 辦法履行。可以修正對象的狀況,但如許 start() 將會掉敗。例如,將敕令屬性設置為一個空列表將不會拋出異常,除非包括了 start()。
留意,此類不是同步的。假如多個線程同時拜訪一個 ProcessBuilder,而個中至多一個線程從構造上修正了個中一個屬性,它必需 堅持內部同步。
結構辦法摘要 
ProcessBuilder(List<String> command)  
          應用指定的操作體系法式和參數結構一個過程生成器。   
ProcessBuilder(String... command)  
          應用指定的操作體系法式和參數結構一個過程生成器。   
 
辦法摘要 
 List<String> command()  
          前往此過程生成器的操作體系法式和參數。 
 ProcessBuilder command(List<String> command)  
          設置此過程生成器的操作體系法式和參數。 
 ProcessBuilder command(String... command)  
          設置此過程生成器的操作體系法式和參數。 
 File directory()  
          前往此過程生成器的任務目次。 
 ProcessBuilder directory(File directory)  
          設置此過程生成器的任務目次。 
 Map<String,String> environment()  
          前往此過程生成器情況的字符串映照視圖。 
 boolean redirectErrorStream()  
          告訴過程生成器能否歸並尺度毛病和尺度輸入。 
 ProcessBuilder redirectErrorStream(boolean redirectErrorStream)  
          設置此過程生成器的 redirectErrorStream 屬性。 
 Process start()  
          應用此過程生成器的屬性啟動一個新過程。 

1.2 Runtime 
  每一個 Java 運用法式都有一個 Runtime 類實例,使運用法式可以或許與其運轉的情況相銜接。可以經由過程 getRuntime 辦法獲得以後運轉時。
  運用法式不克不及創立本身的 Runtime 類實例。但可以經由過程 getRuntime 辦法獲得以後Runtime運轉時對象的援用。一旦獲得了一個以後的Runtime對象的援用,便可以挪用Runtime對象的辦法去掌握Java虛擬機的狀況和行動。
Java代碼  珍藏代碼
void addShutdownHook(Thread hook)  
          注冊新的虛擬機來封閉掛鉤。 
 int availableProcessors()  
          向 Java 虛擬機前往可用途理器的數量。 
 Process exec(String command)  
          在零丁的過程中履行指定的字符串敕令。 
 Process exec(String[] cmdarray)  
          在零丁的過程中履行指天命令和變量。 
 Process exec(String[] cmdarray, String[] envp)  
          在指定情況的自力過程中履行指天命令和變量。 
 Process exec(String[] cmdarray, String[] envp, File dir)  
          在指定情況和任務目次的自力過程中履行指定的敕令和變量。 
 Process exec(String command, String[] envp)  
          在指定情況的零丁過程中履行指定的字符串敕令。 
 Process exec(String command, String[] envp, File dir)  
          在有指定情況和任務目次的自力過程中履行指定的字符串敕令。 
 void exit(int status)  
          經由過程啟動虛擬機的封閉序列,終止以後正在運轉的 Java 虛擬機。 
 long freeMemory()  
          前往 Java 虛擬機中的余暇內存量。 
 void gc()  
          運轉渣滓收受接管器。 
 InputStream getLocalizedInputStream(InputStream in)  
          已過時。 從 JDK 1.1 開端,將當地編碼字撙節轉換為 Unicode 字符流的首選辦法是應用 InputStreamReader 和 BufferedReader 類。 
 OutputStream getLocalizedOutputStream(OutputStream out)  
          已過時。 從 JDK 1.1 開端,將 Unicode 字符流轉換為當地編碼字撙節的首選辦法是應用 OutputStreamWriter、BufferedWriter 和 PrintWriter 類。 
static Runtime getRuntime()  
          前往與以後 Java 運用法式相干的運轉時對象。 
 void halt(int status)  
          強行終止今朝正在運轉的 Java 虛擬機。 
 void load(String filename)  
          加載作為靜態庫的指定文件名。 
 void loadLibrary(String libname)  
          加載具有指定庫名的靜態庫。 
 long maxMemory()  
          前往 Java 虛擬機試圖應用的最年夜內存量。 
 boolean removeShutdownHook(Thread hook)  
          撤消注冊某個先前已注冊的虛擬機封閉掛鉤。 
 void runFinalization()  
          運轉掛起 finalization 的一切對象的終止辦法。 
static void runFinalizersOnExit(boolean value)  
          已過時。 此辦法自己具有不平安性。它能夠對正在應用的對象挪用終結辦法,而其他線程正在操作這些對象,從而招致不准確的行動或逝世鎖。 
 long totalMemory()  
          前往 Java 虛擬機中的內存總量。 
 void traceInstructions(boolean on)  
          啟用/禁用指令跟蹤。 
 void traceMethodCalls(boolean on)  
          啟用/禁用辦法挪用跟蹤。 

1.3 Process
不論經由過程那種辦法啟動過程後,都邑前往一個Process類的實例代表啟動的過程,該實例可用來掌握過程並取得相干信息。Process 類供給了履行從過程輸出、履行輸入到過程、期待過程完成、檢討過程的加入狀況和燒毀(殺失落)過程的辦法:

void destroy()  
          殺失落子過程。 
         普通情形下,該辦法其實不能殺失落曾經啟動的過程,不消為好。 
int exitValue()  
          前往子過程的出口值。  
          只要啟動的過程履行完成、或許因為異常加入後,exitValue()辦法才會有正常的前往值,不然拋出異常。 
InputStream getErrorStream()  
          獲得子過程的毛病流。 
         假如毛病輸入被重定向,則不克不及從該流中讀取毛病輸入。 
InputStream getInputStream()  
          獲得子過程的輸出流。 
          可以從該流中讀取過程的尺度輸入。 
OutputStream getOutputStream()  
          獲得子過程的輸入流。 
          寫入到該流中的數據作為過程的尺度輸出。 
int waitFor()  
          招致以後線程期待,若有需要,一向要比及由該 Process 對象表現的過程曾經終止。

2.多過程編程實例
普通我們在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(); // 樹立子過程

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved