多进程:Java的多进程运行模式分析

般我们在java中运行其它类中思路方法时无论是静态还是动态都是在当前进程中执行也就是说只有个java虚拟机例子在运行而有时候我们需要通过java代码启动多个java子进程这样做虽然占用了些系统资源但会使更加稳定新启动是在区别虚拟机进程中运行如果有个进程发生异常并不影响其它子进程

在Java中我们可以使用两种思路方法来实现这种要求最简单思路方法就是通过Runtime中exec思路方法执行java name如果执行成功这个思路方法返回个Process对象如果执行失败将抛出个IOException下面让我们来看个简单例子

// Test1.java文件
import java.io.*;
public Test
{
public void (String args)
{
FileOutputStream fOut = FileOutputStream("c:\\Test1.txt");
fOut.close;
.out.prln("被成功!");
}
}

// Test_Exec.java
public Test_Exec
{
public void (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 Test_Exec_Out
{
public void (String args)
{
Runtime run = Runtime.getRuntime;
Process p = run.exec("java test1");
BufferedInputStream in = BufferedInputStream(p.getInputStream);
BufferedReader br = BufferedReader( InputStreamReader(in));
String s;
while ((s = br.readLine) != null)
.out.prln(s);
}
}

从上面代码可以看出在Test_Exec_Out.java中通过按行读取子进程输出信息然后在Test_Exec_Out中按每行进行输出上面讨论是如何得到子进程输出信息那么除了输出信息还有输入信息既然子进程没有自己控制台那么输入信息也得由父进程提供我们可以通过 ProcessgetOutputStream思路方法来为子进程提供输入信息(即由父进程向子进程输入信息而不是由控制台输入信息)我们可以看看如下代码:

// Test2.java文件
import java.io.*;
public Test
{
public void (String args)
{
BufferedReader br = BufferedReader( InputStreamReader(.in));
.out.prln("由父进程输入信息:" + br.readLine);
}
}

// Test_Exec_In.java
import java.io.*;
public Test_Exec_In
{
public void (String args)
{
Runtime run = Runtime.getRuntime;
Process p = run.exec("java test2");
BufferedWriter bw = BufferedWriter( OutputStreamWriter(p.getOutputStream));
bw.write("向子进程输出信息");
bw.flush;
bw.close; // 必须得关闭流否则无法向子进程中输入信息
// .in.read;
 }
}

从以上代码可以看出Test1得到由Test_Exec_In发过来信息并将其输出当你不加bw.flash和bw.close信息将无法到达子进程也就是说子进程进入阻塞状态但由于父进程已经退出了因此子进程也跟着退出了如果要证明这可以在最后加上 .in.read然后通过任务管理器(在windows下)查看java进程你会发现如果加上bw.flush和 bw.close只有个java进程存在如果去掉它们就有两个java进程存在这是如果将信息传给Test2在得到信息后 Test2就退出了在这里有点需要介绍说明exec执行是异步并不会执行某个阻塞而停止执行下面代码因此可以在运行 test2后仍可以执行下面代码
exec思路方法经过了多次重载上面使用只是它种重载它还可以将命令和参数分开如exec("java.test2")可以写成exec("java", "test2")exec还可以通过指定环境变量运行区别配置java虚拟机

除了使用Runtimeexec思路方法建立子进程外还可以通过ProcessBuilder建立子进程ProcessBuilder使用思路方法如下:

// Test_Exec_Out.java
import java.io.*;
public Test_Exec_Out
{
public void (String args)
{
ProcessBuilder pb = ProcessBuilder("java", "test1");
Process p = pb.start;
… …
}
}
在建立子进程上ProcessBuilder和Runtime类似区别ProcessBuilder使用start思路方法启动子进程而Runtime使用exec思路方法启动子进程得到Process后它们操作就完全

ProcessBuilder和Runtime也可设置可执行文件环境信息、工作目录等下面例子描述了如何使用ProcessBuilder设置这些信息

ProcessBuilder pb = ProcessBuilder("Command", "arg2", "arg2", ''');
// 设置环境变量
Map env = pb.environment;
env.put("key1", "value1");
env.remove("key2");
env.put("key2", env.get("key1") + "_test");
pb.directory("..\abcd"); // 设置工作目录
Process p = pb.start; // 建立子进程
Tags:  什么是多进程 多线程多进程区别 linux多进程 多进程

延伸阅读

最新评论

发表评论