自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java的多進程運行模式分析

開發(fā) 后端
有的時候,我們需要通過Java代碼啟動多個Java子進程。在Java中我們可以使用兩種方法來實現(xiàn)這種要求。最簡單的方法就是通過Runtime中的exec方法執(zhí)行Java classname。

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

在Java中我們可以使用兩種方法來實現(xiàn)這種要求。最簡單的方法就是通過Runtime中的exec方法執(zhí)行Java classname。如果執(zhí)行成功,這個方法返回一個Process對象,如果執(zhí)行失敗,將拋出一個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("被調(diào)用成功!");
 }
}

// 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運行程序后,發(fā)現(xiàn)在C盤多了個Test1.txt文件,但在控制臺中并未出現(xiàn)"被調(diào)用成功!"的輸出信息。因此可以斷定,Test已經(jīng)被執(zhí)行成功,但因為某種原因,Test的輸出信息未在Test_Exec的控制臺中輸出。這個原因也很簡單,因為使用exec建立的是Test_Exec的子進程,這個子進程并沒有自己的控制臺,因此,它并不會輸出任何信息。

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

// 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(); // 必須得關(guān)閉流,否則無法向子進程中輸入信息
  // System.in.read();
 }
}

從以上代碼可以看出,Test1得到由Test_Exec_In發(fā)過來的信息,并將其輸出。當(dāng)你不加bw.flash()和bw.close()時,信息將無法到達子進程,也就是說子進程進入阻塞狀態(tài),但由于父進程已經(jīng)退出了,因此,子進程也跟著退出了。如果要證明這一點,可以在最后加上System.in.read(),然后通過任務(wù)管理器(在windows下)查看Java進程,你會發(fā)現(xiàn)如果加上bw.flush()和bw.close(),只有一個Java進程存在,如果去掉它們,就有兩個Java進程存在。這是因為,如果將信息傳給Test2,在得到信息后,Test2就退出了。在這里有一點需要說明一下,exec的執(zhí)行是異步的,并不會因為執(zhí)行的某個程序阻塞而停止執(zhí)行下面的代碼。因此,可以在運行test2后,仍可以執(zhí)行下面的代碼。

exec方法經(jīng)過了多次的重載。上面使用的只是它的一種重載。它還可以將命令和參數(shù)分開,如exec("Java.test2")可以寫成exec("Java", "test2")。exec還可以通過指定的環(huán)境變量運行不同配置的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一樣,也可設(shè)置可執(zhí)行文件的環(huán)境信息、工作目錄等。下面的例子描述了如何使用ProcessBuilder設(shè)置這些信息。

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

【編輯推薦】

  1. Java多線程編程基礎(chǔ)之線程和多線程
  2. 詳解Java多線程開發(fā)中的數(shù)據(jù)同步
  3. 簡單理解Java中的輸出流異常
責(zé)任編輯:佚名 來源: cn-java 
相關(guān)推薦

2016-01-11 10:29:36

Docker容器容器技術(shù)

2024-08-26 08:39:26

PHP孤兒進程僵尸進程

2017-06-30 10:12:46

Python多進程

2010-07-15 12:51:17

Perl多進程

2019-02-26 11:15:25

進程多線程多進程

2021-09-10 21:25:43

Redis分布式

2019-03-12 09:20:09

shell爬蟲命名

2010-07-15 13:13:21

Perl多進程

2021-06-16 07:21:39

AndroidAndroid系統(tǒng)多進程通訊

2022-04-19 20:39:03

協(xié)程多進程

2012-08-08 09:32:26

C++多進程并發(fā)框架

2023-12-13 09:56:13

?多進程多線程協(xié)程

2024-12-27 08:11:44

Python編程模式IO

2024-03-29 06:44:55

Python多進程模塊工具

2021-10-12 09:52:30

Webpack 前端多進程打包

2021-02-25 11:19:37

谷歌Android開發(fā)者

2022-03-09 17:01:32

Python多線程多進程

2020-11-18 09:06:04

Python

2021-04-20 12:39:52

Node.js多線程多進程

2021-08-04 23:30:28

Node.js開發(fā)線程
點贊
收藏

51CTO技術(shù)棧公眾號